Repository: googleworkspace/node-samples Branch: main Commit: dc39b4f4dca7 Files: 290 Total size: 389.7 KB Directory structure: gitextract_b64kqjz8/ ├── .gemini/ │ ├── GEMINI.md │ ├── config.yaml │ └── settings.json ├── .github/ │ ├── CODEOWNERS │ ├── ISSUE_TEMPLATE.md │ ├── dependabot.yml │ ├── snippet-bot.yml │ ├── sync-repo-settings.yaml │ └── workflows/ │ ├── automation.yml │ ├── lint.yml │ └── test.yml ├── .gitignore ├── .vscode/ │ └── extensions.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── adminSDK/ │ ├── directory/ │ │ ├── index.js │ │ ├── package.json │ │ └── tsconfig.json │ ├── reports/ │ │ ├── index.js │ │ ├── package.json │ │ └── tsconfig.json │ └── reseller/ │ ├── index.js │ ├── package.json │ └── tsconfig.json ├── apps-script/ │ ├── execute/ │ │ ├── index.js │ │ ├── package.json │ │ └── tsconfig.json │ └── quickstart/ │ ├── index.js │ ├── package.json │ └── tsconfig.json ├── biome.json ├── calendar/ │ └── quickstart/ │ ├── index.js │ ├── package.json │ └── tsconfig.json ├── chat/ │ ├── client-libraries/ │ │ └── cloud/ │ │ ├── authentication-utils.js │ │ ├── create-custom-emoji-user-cred.js │ │ ├── create-membership-user-cred-for-app.js │ │ ├── create-membership-user-cred-for-group.js │ │ ├── create-membership-user-cred.js │ │ ├── create-message-app-cred.js │ │ ├── create-message-user-cred-at-mention.js │ │ ├── create-message-user-cred-message-id.js │ │ ├── create-message-user-cred-request-id.js │ │ ├── create-message-user-cred-thread-key.js │ │ ├── create-message-user-cred-thread-name.js │ │ ├── create-message-user-cred.js │ │ ├── create-reaction-user-cred.js │ │ ├── create-space-user-cred.js │ │ ├── delete-custom-emoji-user-cred.js │ │ ├── delete-membership-user-cred.js │ │ ├── delete-message-app-cred.js │ │ ├── delete-message-user-cred.js │ │ ├── delete-reaction-user-cred.js │ │ ├── delete-space-user-cred.js │ │ ├── find-dm-space-app-cred.js │ │ ├── find-dm-space-user-cred.js │ │ ├── get-attachment-app-cred.js │ │ ├── get-custom-emoji-user-cred.js │ │ ├── get-membership-app-cred.js │ │ ├── get-membership-user-cred.js │ │ ├── get-message-app-cred.js │ │ ├── get-message-user-cred.js │ │ ├── get-space-app-cred.js │ │ ├── get-space-event-user-cred.js │ │ ├── get-space-notification-setting-user-cred.js │ │ ├── get-space-read-state-user-cred.js │ │ ├── get-space-user-cred.js │ │ ├── get-thread-read-state-user-cred.js │ │ ├── list-custom-emojis-user-cred.js │ │ ├── list-memberships-app-cred.js │ │ ├── list-memberships-user-cred.js │ │ ├── list-messages-user-cred.js │ │ ├── list-reactions-user-cred.js │ │ ├── list-space-events-user-cred.js │ │ ├── list-spaces-app-cred.js │ │ ├── list-spaces-user-cred.js │ │ ├── package.json │ │ ├── set-up-space-user-cred.js │ │ ├── tsconfig.json │ │ ├── update-membership-user-cred.js │ │ ├── update-message-app-cred.js │ │ ├── update-message-user-cred.js │ │ ├── update-space-notification-setting-user-cred.js │ │ ├── update-space-read-state-user-cred.js │ │ └── update-space-user-cred.js │ └── quickstart/ │ ├── index.js │ ├── package.json │ └── tsconfig.json ├── classroom/ │ └── quickstart/ │ ├── index.js │ ├── package.json │ └── tsconfig.json ├── docs/ │ └── quickstart/ │ ├── index.js │ ├── package.json │ └── tsconfig.json ├── drive/ │ ├── activity-v2/ │ │ ├── index.js │ │ ├── package.json │ │ └── tsconfig.json │ ├── quickstart/ │ │ ├── index.js │ │ ├── package.json │ │ └── tsconfig.json │ └── snippets/ │ ├── drive_v2/ │ │ ├── appdata_snippets/ │ │ │ ├── fetch_appdata_folder.js │ │ │ ├── list_appdata.js │ │ │ ├── package.json │ │ │ ├── tsconfig.json │ │ │ └── upload_appdata.js │ │ ├── change_snippets/ │ │ │ ├── fetch_changes.js │ │ │ ├── fetch_start_page_token.js │ │ │ ├── package.json │ │ │ └── tsconfig.json │ │ ├── drive_snippets/ │ │ │ ├── create_drive.js │ │ │ ├── package.json │ │ │ ├── recover_drives.js │ │ │ └── tsconfig.json │ │ └── file snippets/ │ │ ├── create_folder.js │ │ ├── create_shortcut.js │ │ ├── download_file.js │ │ ├── export_pdf.js │ │ ├── move_file_to_folder.js │ │ ├── package.json │ │ ├── search_file.js │ │ ├── share_file.js │ │ ├── touch_file.js │ │ ├── tsconfig.json │ │ ├── upload_basic.js │ │ ├── upload_to_folder.js │ │ └── upload_with_conversion.js │ ├── drive_v3/ │ │ ├── appdata_snippets/ │ │ │ ├── fetch_appdata_folder.js │ │ │ ├── list_appdata.js │ │ │ ├── package.json │ │ │ ├── tsconfig.json │ │ │ └── upload_appdata.js │ │ ├── change_snippets/ │ │ │ ├── fetch_changes.js │ │ │ ├── fetch_start_page_token.js │ │ │ ├── package.json │ │ │ └── tsconfig.json │ │ ├── drive_snippets/ │ │ │ ├── create_drive.js │ │ │ ├── package.json │ │ │ ├── recover_drives.js │ │ │ └── tsconfig.json │ │ └── file_snippets/ │ │ ├── create_folder.js │ │ ├── create_shortcut.js │ │ ├── download_file.js │ │ ├── export_pdf.js │ │ ├── move_file_to_folder.js │ │ ├── package.json │ │ ├── search_file.js │ │ ├── share_file.js │ │ ├── touch_file.js │ │ ├── tsconfig.json │ │ ├── upload_basic.js │ │ ├── upload_to_folder.js │ │ └── upload_with_conversion.js │ ├── files/ │ │ ├── config.json │ │ ├── document.txt │ │ └── report.csv │ └── test/ │ ├── helpers.js │ ├── test_drive_v2_create_drive.js │ ├── test_drive_v2_create_folder.js │ ├── test_drive_v2_create_shortcut.js │ ├── test_drive_v2_download_file.js │ ├── test_drive_v2_export_pdf.js │ ├── test_drive_v2_fetch_appdata_folder.js │ ├── test_drive_v2_fetch_changes.js │ ├── test_drive_v2_fetch_start_page_token.js │ ├── test_drive_v2_list_appdata.js │ ├── test_drive_v2_move_file_to_folder.js │ ├── test_drive_v2_recover_drives.js │ ├── test_drive_v2_search_file.js │ ├── test_drive_v2_share_file.js │ ├── test_drive_v2_touch_file.js │ ├── test_drive_v2_upload_appdata.js │ ├── test_drive_v2_upload_basic.js │ ├── test_drive_v2_upload_to_folder.js │ ├── test_drive_v2_upload_with_conversion.js │ ├── test_drive_v3_create_drive.js │ ├── test_drive_v3_create_folder.js │ ├── test_drive_v3_create_shortcut.js │ ├── test_drive_v3_download_file.js │ ├── test_drive_v3_export_pdf.js │ ├── test_drive_v3_fetch_appdata_folder.js │ ├── test_drive_v3_fetch_changes.js │ ├── test_drive_v3_fetch_start_page_token.js │ ├── test_drive_v3_list_appdata.js │ ├── test_drive_v3_move_file_to_folder.js │ ├── test_drive_v3_recover_drives.js │ ├── test_drive_v3_search_file.js │ ├── test_drive_v3_share_file.js │ ├── test_drive_v3_touch_file.js │ ├── test_drive_v3_upload_appdata.js │ ├── test_drive_v3_upload_basic.js │ ├── test_drive_v3_upload_to_folder.js │ └── test_drive_v3_upload_with_conversion.js ├── forms/ │ └── snippets/ │ ├── add_item.js │ ├── add_responder.js │ ├── anyone_with_link_responder.js │ ├── convert_form.js │ ├── create_form.js │ ├── create_watch.js │ ├── delete_watch.js │ ├── get_all_responses.js │ ├── get_form.js │ ├── get_responders.js │ ├── get_single_response.js │ ├── list_watches.js │ ├── package.json │ ├── publish_form.js │ ├── remove_responders.js │ ├── renew_watch.js │ ├── stop_accepting_responses.js │ ├── supports_publishing.js │ ├── tsconfig.json │ ├── unpublish_form.js │ └── update_form.js ├── gmail/ │ └── quickstart/ │ ├── index.js │ ├── package.json │ └── tsconfig.json ├── meet/ │ ├── README.md │ └── quickstart/ │ ├── index.js │ ├── package.json │ └── tsconfig.json ├── package.json ├── people/ │ └── quickstart/ │ ├── index.js │ ├── package.json │ └── tsconfig.json ├── pnpm-workspace.yaml ├── sheets/ │ ├── quickstart/ │ │ ├── index.js │ │ ├── package.json │ │ └── tsconfig.json │ └── snippets/ │ ├── package.json │ ├── sheets_append_values.js │ ├── sheets_batch_get_values.js │ ├── sheets_batch_update.js │ ├── sheets_batch_update_values.js │ ├── sheets_conditional_formatting.js │ ├── sheets_create.js │ ├── sheets_get_values.js │ ├── sheets_pivot_table.js │ ├── sheets_update_values.js │ ├── test/ │ │ ├── helpers.js │ │ ├── test_sheets_append_values.js │ │ ├── test_sheets_batch_get_values.js │ │ ├── test_sheets_batch_update.js │ │ ├── test_sheets_batch_update_values.js │ │ ├── test_sheets_conditional_formatting.js │ │ ├── test_sheets_create.js │ │ ├── test_sheets_get_values.js │ │ ├── test_sheets_pivot_table.js │ │ └── test_sheets_update_values.js │ └── tsconfig.json ├── slides/ │ ├── quickstart/ │ │ ├── index.js │ │ ├── package.json │ │ └── tsconfig.json │ └── snippets/ │ ├── package.json │ ├── slides_copy_presentation.js │ ├── slides_create_bulleted_text.js │ ├── slides_create_image.js │ ├── slides_create_presentation.js │ ├── slides_create_sheets_chart.js │ ├── slides_create_slide.js │ ├── slides_create_textbox_with_text.js │ ├── slides_image_merging.js │ ├── slides_refresh_sheets_chart.js │ ├── slides_simple_text_replace.js │ ├── slides_text_merging.js │ ├── slides_text_style_update.js │ ├── test/ │ │ ├── helpers.js │ │ ├── test_slides_copy_presentation.js │ │ ├── test_slides_create_bulleted_text.js │ │ ├── test_slides_create_image.js │ │ ├── test_slides_create_presentation.js │ │ ├── test_slides_create_sheets_chart.js │ │ ├── test_slides_create_slide.js │ │ ├── test_slides_create_textbox_with_text.js │ │ ├── test_slides_image_merging.js │ │ ├── test_slides_refresh_sheets_chart.js │ │ ├── test_slides_simple_text_replace.js │ │ ├── test_slides_text_merging.js │ │ └── test_slides_text_style_update.js │ └── tsconfig.json ├── solutions/ │ └── webhook-chat-app/ │ ├── README.md │ ├── index.js │ ├── package.json │ └── thread-reply.js ├── tasks/ │ └── quickstart/ │ ├── index.js │ ├── package.json │ └── tsconfig.json ├── tsconfig.base.json └── turbo.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gemini/GEMINI.md ================================================ # Overview This codebase is part of the Google Workspace GitHub organization, https://github.com/googleworkspace. ## Style Guide Use open source best practices for code style and formatting with a preference for Google's style guides. ## Tools - Verify against Google Workspace documentation with the `workspace-developer` MCP server tools. - Use `gh` for GitHub interactions. ================================================ FILE: .gemini/config.yaml ================================================ # Config for the Gemini Pull Request Review Bot. # https://github.com/marketplace/gemini-code-assist have_fun: false code_review: disable: false comment_severity_threshold: "HIGH" max_review_comments: -1 pull_request_opened: help: false summary: true code_review: true ignore_patterns: [] ================================================ FILE: .gemini/settings.json ================================================ { "mcpServers": { "workspace-developer": { "httpUrl": "https://workspace-developer.goog/mcp", "trust": true } } } ================================================ FILE: .github/CODEOWNERS ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners .github/ @googleworkspace/workspace-devrel-dpe ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ # Summary TODO ## Expected Behavior Sample URL: Description: ## Actual Behavior ## Steps to Reproduce the Problem 1. 1. 1. ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: "npm" directory: "/" schedule: interval: "weekly" commit-message: prefix: "chore(deps):" # For pnpm with a catalog, we want to update the versions in the manifest files. versioning-strategy: increase groups: # Group all dependencies into a single PR. all-deps: patterns: - "*" ================================================ FILE: .github/snippet-bot.yml ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ================================================ FILE: .github/sync-repo-settings.yaml ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # .github/sync-repo-settings.yaml # See https://github.com/googleapis/repo-automation-bots/tree/main/packages/sync-repo-settings for app options. rebaseMergeAllowed: true squashMergeAllowed: true mergeCommitAllowed: false deleteBranchOnMerge: true branchProtectionRules: - pattern: main isAdminEnforced: false requiresStrictStatusChecks: false requiredStatusCheckContexts: # .github/workflows/test.yml with a job called "test" - "test" # .github/workflows/lint.yml with a job called "lint" - "lint" # Google bots below - "cla/google" - "snippet-bot check" - "header-check" - "conventionalcommits.org" requiredApprovingReviewCount: 1 requiresCodeOwnerReviews: true permissionRules: - team: workspace-devrel-dpe permission: admin - team: workspace-devrel permission: push ================================================ FILE: .github/workflows/automation.yml ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. --- name: Automation on: [ push, pull_request, workflow_dispatch ] jobs: dependabot: runs-on: ubuntu-latest if: ${{ github.actor == 'dependabot[bot]' && github.event_name == 'pull_request' }} env: PR_URL: ${{github.event.pull_request.html_url}} GITHUB_TOKEN: ${{secrets.GOOGLEWORKSPACE_BOT_TOKEN}} steps: - name: approve run: gh pr review --approve "$PR_URL" - name: merge run: gh pr merge --auto --squash --delete-branch "$PR_URL" default-branch-migration: # this job helps with migrating the default branch to main # it pushes main to master if master exists and main is the default branch # it pushes master to main if master is the default branch runs-on: ubuntu-latest if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' }} steps: - uses: actions/checkout@v2 with: fetch-depth: 0 # required otherwise GitHub blocks infinite loops in pushes originating in an action token: ${{ secrets.GOOGLEWORKSPACE_BOT_TOKEN }} - name: Set env run: | # set DEFAULT BRANCH echo "DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name')" >> "$GITHUB_ENV"; # set HAS_MASTER_BRANCH if [ -n "$(git ls-remote --heads origin master)" ]; then echo "HAS_MASTER_BRANCH=true" >> "$GITHUB_ENV" else echo "HAS_MASTER_BRANCH=false" >> "$GITHUB_ENV" fi env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: configure git run: | git config --global user.name 'googleworkspace-bot' git config --global user.email 'googleworkspace-bot@google.com' - if: ${{ env.DEFAULT_BRANCH == 'main' && env.HAS_MASTER_BRANCH == 'true' }} name: Update master branch from main run: | git checkout -B master git reset --hard origin/main git push origin master - if: ${{ env.DEFAULT_BRANCH == 'master'}} name: Update main branch from master run: | git checkout -B main git reset --hard origin/master git push origin main ================================================ FILE: .github/workflows/lint.yml ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. --- name: Lint on: push: branches: - main pull_request: jobs: lint: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}-${{ github.head_ref || github.ref }} cancel-in-progress: true runs-on: ubuntu-latest steps: - uses: actions/checkout@v3.0.0 with: fetch-depth: 0 - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 with: cache: 'pnpm' - run: pnpm i - run: pnpm lint ================================================ FILE: .github/workflows/test.yml ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. name: Test on: push: branches: - main pull_request: jobs: test: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}-${{ github.head_ref || github.ref }} cancel-in-progress: true runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 with: cache: "pnpm" - run: pnpm i - run: pnpm check # Tests are failing due to scope/grant errors. # - name: Write test credentials # run: | # mkdir "${HOME}/secrets" # echo "${DEFAULT_CREDENTIALS}" > "${HOME}/secrets/default_credentials.json" # echo "${SERVICE_ACCOUNT_CREDENTIALS}" > "${HOME}/secrets/service_account.json" # echo "${CLIENT_ID_FILE}" > "${HOME}/secrets/client_id.json" # env: # DEFAULT_CREDENTIALS: ${{secrets.SNIPPETS_DEFAULT_CREDENTIALS}} # SERVICE_ACCOUNT_CREDENTIALS: ${{secrets.SNIPPETS_DELEGATED_ADMIN_SERVICE_ACCOUNT}} # CLIENT_ID_FILE: ${{secrets.SNIPPETS_CLIENT_ID_FILE}} # - name: Run tests # run: | # export GOOGLE_APPLICATION_CREDENTIALS="${HOME}/secrets/default_credentials.json" # export SERVICE_ACCOUNT_CREDENTIALS="${HOME}/secrets/service_account.json" # pnpm test # env: # GOOGLE_CLOUD_PROJECT: workspace-samples-ci ================================================ FILE: .gitignore ================================================ # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Runtime data pids *.pid *.seed *.lock # Dependency directories node_modules/ # dotenv environment variables file .env .DS_Store client_secret.json application_credentials.json credentials.json token.json .turbo ================================================ FILE: .vscode/extensions.json ================================================ { "recommendations": [ "google-workspace.google-workspace-developer-tools" ] } ================================================ FILE: CONTRIBUTING.md ================================================ # How to become a contributor and submit your own code ## Contributor License Agreements We'd love to accept your sample apps and patches! Before we can take them, we have to jump a couple of legal hurdles. Please fill out either the individual or corporate Contributor License Agreement (CLA). * If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an [individual CLA](https://developers.google.com/open-source/cla/individual). * If you work for a company that wants to allow you to contribute your work, then you'll need to sign a [corporate CLA](https://developers.google.com/open-source/cla/corporate). Follow either of the two links above to access the appropriate CLA and instructions for how to sign and return it. Once we receive it, we'll be able to accept your pull requests. ## Contributing A Patch 1. Submit an issue describing your proposed change to the repository in question. 1. The repository owner will respond to your issue promptly. 1. If your proposed change is accepted, and you haven't already done so, sign a Contributor License Agreement (see details above). 1. Fork the desired repository, develop and test your code changes. 1. Ensure that your code adheres to the existing style in the sample to which you are contributing. 1. Ensure that your code has an appropriate set of unit tests which all pass. 1. Submit a pull request! ## Style Samples in this repository follow the [JavaScript Semi-Standard Style](https://github.com/Flet/semistandard). ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # Node.js samples for [Google Workspace APIs](https://developers.google.com/workspace/) docs This repository contains Node.js samples for Google Workspace APIs. ## Development 1. Install [Node.js](https://nodejs.org). 1. Install `pnpm` by running `npm install -g pnpm` or see additional options at https://pnpm.io/installation. `pnpm` is used with `turborepo` to better handled the many packages in the repository. 1. Create a Service Account Before running tests, create a service account and download `application_credentials.json` in this directory. To create a service account, follow these steps: 1. Navigate to the [Google Cloud Console API Dashboard](https://console.cloud.google.com/apis/dashboard) 1. Enable APIs for products you'd like to test snippets for like Slides or Drive. 1. Create a service account key under [Credentials](https://console.cloud.google.com/apis/credentials). 1. After creating a new JSON Service account key without a role and set the env variable `SERVICE_ACCOUNT_CREDENTIALS=some/path/to/application_credentials.json`. 1. `pnpm test` 1. `pnpm lint` 1. Delete service account file. 1. `pnpx codemod pnpm/catalog` to add package dependencies to the catalog. 1. `pnpm -r -L update` to update all package depencies to the latest version. ## Contributing Contributions welcome! See the [Contributing Guide](CONTRIBUTING.md). ================================================ FILE: SECURITY.md ================================================ # Report a security issue To report a security issue, please use [https://g.co/vulnz](https://g.co/vulnz). We use [https://g.co/vulnz](https://g.co/vulnz) for our intake, and do coordination and disclosure here on GitHub (including using GitHub Security Advisory). The Google Security Team will respond within 5 working days of your report on [https://g.co/vulnz](https://g.co/vulnz). ================================================ FILE: adminSDK/directory/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START admin_sdk_directory_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; // The scope for the Admin SDK Directory API. const SCOPES = ['https://www.googleapis.com/auth/admin.directory.user']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Lists the first 10 users in the domain. */ async function listUsers() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Admin SDK Directory API client. const service = google.admin({version: 'directory_v1', auth}); // Get the list of users. const result = await service.users.list({ customer: 'my_customer', maxResults: 10, orderBy: 'email', }); const users = result.data.users; if (!users || users.length === 0) { console.log('No users found.'); return; } // Print the primary email and full name of each user. console.log('Users:'); users.forEach((user) => { console.log(`${user.primaryEmail} (${user.name?.fullName})`); }); } await listUsers(); // [END admin_sdk_directory_quickstart] ================================================ FILE: adminSDK/directory/package.json ================================================ { "name": "google-admin-directory-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google Drive API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: adminSDK/directory/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: adminSDK/reports/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START admin_sdk_reports_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; // The scope for the Admin SDK Reports API. const SCOPES = ['https://www.googleapis.com/auth/admin.reports.audit.readonly']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Lists the last 10 login events for the domain. */ async function listLoginEvents() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Admin SDK Reports API client. const service = google.admin({version: 'reports_v1', auth}); // Get the list of login events. const result = await service.activities.list({ userKey: 'all', applicationName: 'login', maxResults: 10, }); const activities = result.data.items; if (!activities || activities.length === 0) { console.log('No logins found.'); return; } // Print the time, email, and event name of each login event. console.log('Logins:'); activities.forEach((activity) => { console.log( `${activity.id?.time}: ${activity.actor?.email} (${activity.events?.[0]?.name})`, ); }); } await listLoginEvents(); // [END admin_sdk_reports_quickstart] ================================================ FILE: adminSDK/reports/package.json ================================================ { "name": "google-admin-reports-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google Drive API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: adminSDK/reports/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: adminSDK/reseller/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START admin_sdk_reseller_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; // The scope for the Admin SDK Reseller API. const SCOPES = ['https://www.googleapis.com/auth/apps.order']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Lists the first 10 subscriptions you manage. */ async function listSubscriptions() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Admin SDK Reseller API client. const service = google.reseller({version: 'v1', auth}); // Get the list of subscriptions. const result = await service.subscriptions.list({ maxResults: 10, }); const subscriptions = result.data.subscriptions; if (!subscriptions || subscriptions.length === 0) { console.log('No subscriptions found.'); return; } // Print the customer ID, SKU ID, and plan name of each subscription. console.log('Subscriptions:'); subscriptions.forEach(({customerId, skuId, plan}) => { console.log(`${customerId} (${skuId}, ${plan?.planName})`); }); } await listSubscriptions(); // [END admin_sdk_reseller_quickstart] ================================================ FILE: adminSDK/reseller/package.json ================================================ { "name": "google-reseller-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google Drive API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: adminSDK/reseller/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: apps-script/execute/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START apps_script_api_execute] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Calls an Apps Script function to list the folders in the user's root Drive folder. */ async function callAppsScript() { // The ID of the Apps Script project to call. const scriptId = '1xGOh6wCm7hlIVSVPKm0y_dL-YqetspS5DEVmMzaxd_6AAvI-_u8DSgBT'; // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Apps Script API client. const script = google.script({version: 'v1', auth}); const resp = await script.scripts.run({ auth, requestBody: { // The name of the function to call in the Apps Script project. function: 'getFoldersUnderRoot', }, scriptId, }); if (resp.data.error?.details?.[0]) { // The API executed, but the script returned an error. // Extract the error details. const error = resp.data.error.details[0]; console.log(`Script error message: ${error.errorMessage}`); console.log('Script error stacktrace:'); if (error.scriptStackTraceElements) { // Log the stack trace. for (let i = 0; i < error.scriptStackTraceElements.length; i++) { const trace = error.scriptStackTraceElements[i]; console.log('\t%s: %s', trace.function, trace.lineNumber); } } } else { // The script executed successfully. // The structure of the response depends on the Apps Script function's return value. const folderSet = resp.data.response ?? {}; if (Object.keys(folderSet).length === 0) { console.log('No folders returned!'); } else { console.log('Folders under your root folder:'); Object.keys(folderSet).forEach((id) => { console.log('\t%s (%s)', folderSet[id], id); }); } } } // [END apps_script_api_execute] callAppsScript(); ================================================ FILE: apps-script/execute/package.json ================================================ { "name": "apps-script-execute", "version": "1.0.0", "private": true, "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" }, "dependencies": { "googleapis": "catalog:" } } ================================================ FILE: apps-script/execute/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: apps-script/quickstart/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START apps_script_api_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; const SCOPES = ['https://www.googleapis.com/auth/script.projects']; const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Creates a new script project, upload a file, and log the script's URL. */ async function callAppsScript() { const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); const script = google.script({version: 'v1', auth}); const project = await script.projects.create({ requestBody: { title: 'My Script', }, }); if (!project.data.scriptId) { throw new Error('Failed to create project'); } await script.projects.updateContent({ scriptId: project.data.scriptId, auth, requestBody: { files: [ { name: 'hello', type: 'SERVER_JS', source: 'function helloWorld() {\n console.log("Hello, world!");\n}', }, { name: 'appsscript', type: 'JSON', source: '{"timeZone":"America/New_York","exceptionLogging":' + '"CLOUD"}', }, ], }, }); console.log(`https://script.google.com/d/${project.data.scriptId}/edit`); } await callAppsScript(); // [END apps_script_api_quickstart] ================================================ FILE: apps-script/quickstart/package.json ================================================ { "name": "google-apps-script-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google Apps Script API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: apps-script/quickstart/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: biome.json ================================================ { "$schema": "https://biomejs.dev/schemas/2.2.4/schema.json", "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true }, "files": { "ignoreUnknown": true }, "formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2, "bracketSpacing": false }, "linter": { "enabled": true, "rules": { "recommended": true } }, "javascript": { "formatter": { "quoteStyle": "single" } }, "assist": { "enabled": true, "actions": { "source": { "organizeImports": "on" } } } } ================================================ FILE: calendar/quickstart/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START calendar_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; // The scope for reading calendar events. const SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Lists the next 10 events on the user's primary calendar. */ async function listEvents() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Calendar API client. const calendar = google.calendar({version: 'v3', auth}); // Get the list of events. const result = await calendar.events.list({ calendarId: 'primary', timeMin: new Date().toISOString(), maxResults: 10, singleEvents: true, orderBy: 'startTime', }); const events = result.data.items; if (!events || events.length === 0) { console.log('No upcoming events found.'); return; } console.log('Upcoming 10 events:'); // Print the start time and summary of each event. for (const event of events) { const start = event.start?.dateTime ?? event.start?.date; console.log(`${start} - ${event.summary}`); } } await listEvents(); // [END calendar_quickstart] ================================================ FILE: calendar/quickstart/package.json ================================================ { "name": "google-calendar-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google Calendar API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: calendar/quickstart/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: chat/client-libraries/cloud/authentication-utils.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START chat_authentication_utils] import {readFile} from 'node:fs/promises'; import http from 'node:http'; import url from 'node:url'; import {ChatServiceClient} from '@google-apps/chat'; import {OAuth2Client} from 'google-auth-library'; import open from 'open'; import destroyer from 'server-destroy'; // Application authentication const SERVICE_ACCOUNT_FILE = './service_account.json'; const APP_AUTH_OAUTH_SCOPES = ['https://www.googleapis.com/auth/chat.bot']; // User authentication const CLIENT_SECRETS_FILE = './credentials.json'; const CLIENT_SECRETS = JSON.parse( await readFile(new URL(CLIENT_SECRETS_FILE, import.meta.url), 'utf8'), ).web; /** * Create a new Chat service client with application credentials. * * @return {ChatServiceClient} The resulting client for the Chat service */ export function createClientWithAppCredentials() { // For more information on app authentication, see // https://developers.google.com/workspace/chat/authenticate-authorize-chat-app return new ChatServiceClient({ keyFile: SERVICE_ACCOUNT_FILE, scopes: APP_AUTH_OAUTH_SCOPES, }); } /** * Create a new Chat service client with user credentials and scopes. * * @param {Array} scopes Required scopes for the desired API requests * @return {Promise} The resulting client for the Chat service */ export async function createClientWithUserCredentials(scopes) { // For more information on user authentication, see // https://developers.google.com/workspace/chat/authenticate-authorize-chat-user return new ChatServiceClient({ authClient: await getAuthenticatedUserOAuth2Client(scopes), scopes, }); } /** * Create a new OAuth2 client and go through the OAuth2 flow. * * @param {Array} scopes Required scopes for the desired API requests * @return {Promise} The resulting Google OAuth2 client */ function getAuthenticatedUserOAuth2Client(scopes) { return new Promise((resolve, reject) => { // Create a client based on client secrets const oAuth2Client = new OAuth2Client( CLIENT_SECRETS.client_id, CLIENT_SECRETS.client_secret, CLIENT_SECRETS.redirect_uris[0], ); // Generate the URL to use for consent const authorizeUrl = oAuth2Client.generateAuthUrl({ access_type: 'offline', scope: scopes, }); // Creates and starts an HTTP server to accept the OAuth2 callback. const server = http .createServer(async (request, response) => { try { if (request.url.indexOf('/oauth2callback') > -1) { // Acquire the code and close the server. const queryString = new url.URL( request.url, 'http://localhost:3000', ).searchParams; const code = queryString.get('code'); response.end('Done!'); server.destroy(); // Acquire the tokens const r = await oAuth2Client.getToken(code); // Update credentials of the OAuth2 client. oAuth2Client.setCredentials(r.tokens); resolve(oAuth2Client); } } catch (e) { reject(e); } }) .listen(3000, () => { // Opens the default browser to start the OAuth2 flow. open(authorizeUrl, {wait: false}).then((cp) => cp.unref()); }); destroyer(server); }); } // [END chat_authentication_utils] ================================================ FILE: chat/client-libraries/cloud/create-custom-emoji-user-cred.js ================================================ /** * Copyright 2025 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START chat_create_custom_emoji_user_cred] import fs from 'node:fs'; import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.customemojis', ]; // This sample shows how to create custom emoji with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // TODO(developer) Replace FILENAME here. const filename = 'FILENAME'; // Read custom emoji file content into a base64 encoded string. const fileContent = fs.readFileSync(filename, {encoding: 'base64'}); // Initialize request argument(s) const request = { custom_emoji: { // TODO(developer): Replace EMOJI_NAME here. emoji_name: 'EMOJI_NAME', payload: { file_content: fileContent, filename, }, }, }; // Make the request const response = await chatClient.createCustomEmoji(request); // Handle the response console.log(response); } await main(); // [END chat_create_custom_emoji_user_cred] ================================================ FILE: chat/client-libraries/cloud/create-membership-user-cred-for-app.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_create_membership_user_cred_for_app] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.memberships.app', ]; // This sample shows how to create an app membership. async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here. parent: 'spaces/SPACE_NAME', membership: { member: { // Member name for app membership, do not change this name: 'users/app', // User type for the membership type: 'BOT', }, }, }; // Make the request const response = await chatClient.createMembership(request); // Handle the response console.log(response); } await main(); // [END chat_create_membership_user_cred_for_app] ================================================ FILE: chat/client-libraries/cloud/create-membership-user-cred-for-group.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_create_membership_user_cred_for_group] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.memberships', ]; // This sample shows how to create membership with user credential for a group async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here. parent: 'spaces/SPACE_NAME', membership: { groupMember: { // Replace GROUP_NAME here name: 'groups/GROUP_NAME', }, }, }; // Make the request const response = await chatClient.createMembership(request); // Handle the response console.log(response); } await main(); // [END chat_create_membership_user_cred_for_group] ================================================ FILE: chat/client-libraries/cloud/create-membership-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_create_membership_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.memberships', ]; // This sample shows how to create membership with user credential for a human // user async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here. parent: 'spaces/SPACE_NAME', membership: { member: { // Replace USER_NAME here name: 'users/USER_NAME', // User type for the membership type: 'HUMAN', }, }, }; // Make the request const response = await chatClient.createMembership(request); // Handle the response console.log(response); } await main(); // [END chat_create_membership_user_cred] ================================================ FILE: chat/client-libraries/cloud/create-message-app-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_create_message_app_cred] import {createClientWithAppCredentials} from './authentication-utils.js'; // This sample shows how to create message with app credential async function main() { // Create a client const chatClient = createClientWithAppCredentials(); // Initialize request argument(s) const request = { // Replace SPACE_NAME here. parent: 'spaces/SPACE_NAME', message: { text: '👋🌎 Hello world! I created this message by calling ' + "the Chat API's `messages.create()` method.", cardsV2: [ { card: { header: { title: 'About this message', imageUrl: 'https://fonts.gstatic.com/s/i/short-term/release/googlesymbols/info/default/24px.svg', }, sections: [ { header: 'Contents', widgets: [ { textParagraph: { text: '🔡 Text which can include ' + 'hyperlinks 🔗, emojis 😄🎉, and @mentions 🗣️.', }, }, { textParagraph: { text: '🖼️ A card to display visual elements' + 'and request information such as text 🔤, ' + 'dates and times 📅, and selections ☑️.', }, }, { textParagraph: { text: '👉🔘 An accessory widget which adds ' + 'a button to the bottom of a message.', }, }, ], }, { header: "What's next", collapsible: true, widgets: [ { textParagraph: { text: "❤️ Add a reaction.", }, }, { textParagraph: { text: "🔄 Update " + "or ❌ delete " + 'the message.', }, }, ], }, ], }, }, ], accessoryWidgets: [ { buttonList: { buttons: [ { text: 'View documentation', icon: {materialIcon: {name: 'link'}}, onClick: { openLink: { url: 'https://developers.google.com/workspace/chat/create-messages', }, }, }, ], }, }, ], }, }; // Make the request const response = await chatClient.createMessage(request); // Handle the response console.log(response); } await main(); // [END chat_create_message_app_cred] ================================================ FILE: chat/client-libraries/cloud/create-message-user-cred-at-mention.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_create_message_user_cred_at_mention] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.messages.create', ]; // This sample shows how to create message with user credential with a user // mention async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here. parent: 'spaces/SPACE_NAME', message: { // The user with USER_NAME will be mentioned if they are in the space // Replace USER_NAME here text: 'Hello !', }, }; // Make the request const response = await chatClient.createMessage(request); // Handle the response console.log(response); } await main(); // [END chat_create_message_user_cred_at_mention] ================================================ FILE: chat/client-libraries/cloud/create-message-user-cred-message-id.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_create_message_user_cred_message_id] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.messages.create', ]; // This sample shows how to create a message with user credentials and a custom // message id async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here. parent: 'spaces/SPACE_NAME', // Message id lets chat apps get, update or delete a message without needing // to store the system assigned ID in the message's resource name messageId: 'client-MESSAGE-ID', message: {text: 'Hello with user credential!'}, }; // Make the request const response = await chatClient.createMessage(request); // Handle the response console.log(response); } await main(); // [END chat_create_message_user_cred_message_id] ================================================ FILE: chat/client-libraries/cloud/create-message-user-cred-request-id.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_create_message_user_cred_request_id] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.messages.create', ]; // This sample shows how to create message with user credential with request id async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here. parent: 'spaces/SPACE_NAME', // Specifying an existing request ID returns the message created with // that ID instead of creating a new message requestId: 'REQUEST_ID', message: {text: 'Hello with user credential!'}, }; // Make the request const response = await chatClient.createMessage(request); // Handle the response console.log(response); } await main(); // [END chat_create_message_user_cred_request_id] ================================================ FILE: chat/client-libraries/cloud/create-message-user-cred-thread-key.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_create_message_user_cred_thread_key] import {protos} from '@google-apps/chat'; import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.messages.create', ]; // This sample shows how to create message with user credential with thread key async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here. parent: 'spaces/SPACE_NAME', // Creates the message as a reply to the thread specified by thread_key // If it fails, the message starts a new thread instead messageReplyOption: protos.google.chat.v1.CreateMessageRequest.MessageReplyOption .REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD, message: { text: 'Hello with user credential!', thread: { // Thread key specifies a thread and is unique to the chat app // that sets it threadKey: 'THREAD_KEY', }, }, }; // Make the request const response = await chatClient.createMessage(request); // Handle the response console.log(response); } await main(); // [END chat_create_message_user_cred_thread_key] ================================================ FILE: chat/client-libraries/cloud/create-message-user-cred-thread-name.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_create_message_user_cred_thread_name] import {protos} from '@google-apps/chat'; import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.messages.create', ]; // This sample shows how to create a message with user credentials in a named // thread async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here. parent: 'spaces/SPACE_NAME', // Creates the message as a reply to the thread specified by thread.name. // If it fails, the message starts a new thread instead. messageReplyOption: protos.google.chat.v1.CreateMessageRequest.MessageReplyOption .REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD, message: { text: 'Hello with user credential!', thread: { // Resource name of a thread that uniquely identify a thread // Replace SPACE_NAME and THREAD_NAME here name: 'spaces/SPACE_NAME/threads/THREAD_NAME', }, }, }; // Make the request const response = await chatClient.createMessage(request); // Handle the response console.log(response); } await main(); // [END chat_create_message_user_cred_thread_name] ================================================ FILE: chat/client-libraries/cloud/create-message-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_create_message_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.messages.create', ]; // This sample shows how to create message with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here. parent: 'spaces/SPACE_NAME', message: { text: '👋🌎 Hello world!' + 'Text messages can contain things like:\n\n' + '* Hyperlinks 🔗\n' + '* Emojis 😄🎉\n' + '* Mentions of other Chat users `@` \n\n' + 'For details, see the ' + '.', }, }; // Make the request const response = await chatClient.createMessage(request); // Handle the response console.log(response); } await main(); // [END chat_create_message_user_cred] ================================================ FILE: chat/client-libraries/cloud/create-reaction-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_create_reaction_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.messages.reactions.create', ]; // This sample shows how to create reaction to a message with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME and MESSAGE_NAME here. parent: 'spaces/SPACE_NAME/messages/MESSAGE_NAME', reaction: { // A standard emoji represented by a unicode string. emoji: {unicode: '😀'}, }, }; // Make the request const response = await chatClient.createReaction(request); // Handle the response console.log(response); } await main(); // [END chat_create_reaction_user_cred] ================================================ FILE: chat/client-libraries/cloud/create-space-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_create_space_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.spaces.create', ]; // This sample shows how to create a named space with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { space: { spaceType: 'SPACE', // Replace DISPLAY_NAME here. displayName: 'DISPLAY_NAME', }, }; // Make the request const response = await chatClient.createSpace(request); // Handle the response console.log(response); } await main(); // [END chat_create_space_user_cred] ================================================ FILE: chat/client-libraries/cloud/delete-custom-emoji-user-cred.js ================================================ /** * Copyright 2025 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_delete_custom_emoji_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.customemojis', ]; // This sample shows how to delete a custom emoji with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // TODO(developer): Replace EMOJI_NAME here. name: 'customEmojis/EMOJI_NAME', }; // Make the request const response = await chatClient.deleteCustomEmoji(request); // Handle the response console.log(response); } await main(); // [END chat_delete_custom_emoji_user_cred] ================================================ FILE: chat/client-libraries/cloud/delete-membership-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_delete_membership_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.memberships', ]; // This sample shows how to delete a membership of type HUMAN with user // credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME and MEMBER_NAME here name: 'spaces/SPACE_NAME/members/MEMBER_NAME', }; // Make the request const response = await chatClient.deleteMembership(request); // Handle the response console.log(response); } await main(); // [END chat_delete_membership_user_cred] ================================================ FILE: chat/client-libraries/cloud/delete-message-app-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_delete_message_app_cred] import {createClientWithAppCredentials} from './authentication-utils.js'; // This sample shows how to delete a message with app credential async function main() { // Create a client const chatClient = createClientWithAppCredentials(); // Initialize request argument(s) const request = { // Replace SPACE_NAME and MESSAGE_NAME here name: 'spaces/SPACE_NAME/messages/MESSAGE_NAME', }; // Make the request const response = await chatClient.deleteMessage(request); // Handle the response console.log(response); } await main(); // [END chat_delete_message_app_cred] ================================================ FILE: chat/client-libraries/cloud/delete-message-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_delete_message_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.messages', ]; // This sample shows how to delete a message with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME and MESSAGE_NAME here name: 'spaces/SPACE_NAME/messages/MESSAGE_NAME', }; // Make the request const response = await chatClient.deleteMessage(request); // Handle the response console.log(response); } await main(); // [END chat_delete_message_user_cred] ================================================ FILE: chat/client-libraries/cloud/delete-reaction-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_delete_reaction_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.messages.reactions', ]; // This sample shows how to delete a reaction to a message with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME, MESSAGE_NAME, and REACTION_NAME here name: 'spaces/SPACE_NAME/messages/MESSAGE_NAME/reactions/REACTION_NAME', }; // Make the request const response = await chatClient.deleteReaction(request); // Handle the response console.log(response); } await main(); // [END chat_delete_reaction_user_cred] ================================================ FILE: chat/client-libraries/cloud/delete-space-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_delete_space_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = ['https://www.googleapis.com/auth/chat.delete']; // This sample shows how to delete a space with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here name: 'spaces/SPACE_NAME', }; // Make the request const response = await chatClient.deleteSpace(request); // Handle the response console.log(response); } await main(); // [END chat_delete_space_user_cred] ================================================ FILE: chat/client-libraries/cloud/find-dm-space-app-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_find_dm_space_app_cred] import {createClientWithAppCredentials} from './authentication-utils.js'; // This sample shows how to find a Direct Message space with app credential async function main() { // Create a client const chatClient = createClientWithAppCredentials(); // Initialize request argument(s) const request = { // Replace USER_NAME here name: 'users/USER_NAME', }; // Make the request const response = await chatClient.findDirectMessage(request); // Handle the response console.log(response); } await main(); // [END chat_find_dm_space_app_cred] ================================================ FILE: chat/client-libraries/cloud/find-dm-space-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_find_dm_space_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.spaces.readonly', ]; // This sample shows how to find a Direct Message space with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace USER_NAME here name: 'users/USER_NAME', }; // Make the request const response = await chatClient.findDirectMessage(request); // Handle the response console.log(response); } await main(); // [END chat_find_dm_space_user_cred] ================================================ FILE: chat/client-libraries/cloud/get-attachment-app-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_get_attachment_app_cred] import {createClientWithAppCredentials} from './authentication-utils.js'; // This sample shows how to get attachment metadata with app // credential async function main() { // Create a client const chatClient = createClientWithAppCredentials(); // Initialize request argument(s) const request = { // Replace SPACE_NAME, MESSAGE_NAME, and ATTACHMENT_NAME here name: 'spaces/SPACE_NAME/messages/MESSAGE_NAME/attachments/ATTACHMENT_NAME', }; // Make the request const response = await chatClient.getAttachment(request); // Handle the response console.log(response); } await main(); // [END chat_get_attachment_app_cred] ================================================ FILE: chat/client-libraries/cloud/get-custom-emoji-user-cred.js ================================================ /** * Copyright 2025 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_get_custom_emoji_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.customemojis', ]; // This sample shows how to get custom emoji with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // TODO(developer): Replace EMOJI_NAME here name: 'customEmojis/EMOJI_NAME', }; // Make the request const response = await chatClient.getCustomEmoji(request); // Handle the response console.log(response); } await main(); // [END chat_get_custom_emoji_user_cred] ================================================ FILE: chat/client-libraries/cloud/get-membership-app-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_get_membership_app_cred] import {createClientWithAppCredentials} from './authentication-utils.js'; // This sample shows how to get membership with app credential async function main() { // Create a client const chatClient = createClientWithAppCredentials(); // Initialize request argument(s) const request = { // Replace SPACE_NAME and MEMBER_NAME here name: 'spaces/SPACE_NAME/members/MEMBER_NAME', }; // Make the request const response = await chatClient.getMembership(request); // Handle the response console.log(response); } await main(); // [END chat_get_membership_app_cred] ================================================ FILE: chat/client-libraries/cloud/get-membership-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_get_membership_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.memberships.readonly', ]; // This sample shows how to get membership with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME and MEMBER_NAME here name: 'spaces/SPACE_NAME/members/MEMBER_NAME', }; // Make the request const response = await chatClient.getMembership(request); // Handle the response console.log(response); } await main(); // [END chat_get_membership_user_cred] ================================================ FILE: chat/client-libraries/cloud/get-message-app-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_get_message_app_cred] import {createClientWithAppCredentials} from './authentication-utils.js'; // This sample shows how to get message with app credential async function main() { // Create a client const chatClient = createClientWithAppCredentials(); // Initialize request argument(s) const request = { // Replace SPACE_NAME and MESSAGE_NAME here name: 'spaces/SPACE_NAME/messages/MESSAGE_NAME', }; // Make the request const response = await chatClient.getMessage(request); // Handle the response console.log(response); } await main(); // [END chat_get_message_app_cred] ================================================ FILE: chat/client-libraries/cloud/get-message-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_get_message_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.messages.readonly', ]; // This sample shows how to get message with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME and MESSAGE_NAME here name: 'spaces/SPACE_NAME/messages/MESSAGE_NAME', }; // Make the request const response = await chatClient.getMessage(request); // Handle the response console.log(response); } await main(); // [END chat_get_message_user_cred] ================================================ FILE: chat/client-libraries/cloud/get-space-app-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_get_space_app_cred] import {createClientWithAppCredentials} from './authentication-utils.js'; // This sample shows how to get space with app credential async function main() { // Create a client const chatClient = createClientWithAppCredentials(); // Initialize request argument(s) const request = { // Replace SPACE_NAME here name: 'spaces/SPACE_NAME', }; // Make the request const response = await chatClient.getSpace(request); // Handle the response console.log(response); } await main(); // [END chat_get_space_app_cred] ================================================ FILE: chat/client-libraries/cloud/get-space-event-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START chat_get_space_event_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; // Replace SCOPE_NAME here with an authorization scope based on the event type const USER_AUTH_OAUTH_SCOPES = ['SCOPE_NAME']; // This sample shows how to get space event with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME and SPACE_EVENT_NAME here name: 'spaces/SPACE_NAME/spaceEvents/SPACE_EVENT_NAME', }; // Make the request const response = await chatClient.getSpaceEvent(request); // Handle the response console.log(response); } await main(); // [END chat_get_space_event_user_cred] ================================================ FILE: chat/client-libraries/cloud/get-space-notification-setting-user-cred.js ================================================ /** * Copyright 2025 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_get_space_notification_setting_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.users.spacesettings', ]; // This sample shows how to get the space notification setting for the calling // user async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s), replace the SPACE_NAME with an actual space // name. const request = { name: 'users/me/spaces/SPACE_NAME/spaceNotificationSetting', }; // Make the request const response = await chatClient.getSpaceNotificationSetting(request); // Handle the response console.log(response); } await main(); // [END chat_get_space_notification_setting_user_cred] ================================================ FILE: chat/client-libraries/cloud/get-space-read-state-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_get_space_read_state_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.users.readstate.readonly', ]; // This sample shows how to get the space read state for the calling user async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here name: 'users/me/spaces/SPACE_NAME/spaceReadState', }; // Make the request const response = await chatClient.getSpaceReadState(request); // Handle the response console.log(response); } await main(); // [END chat_get_space_read_state_user_cred] ================================================ FILE: chat/client-libraries/cloud/get-space-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_get_space_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.spaces.readonly', ]; // This sample shows how to get space with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here name: 'spaces/SPACE_NAME', }; // Make the request const response = await chatClient.getSpace(request); // Handle the response console.log(response); } await main(); // [END chat_get_space_user_cred] ================================================ FILE: chat/client-libraries/cloud/get-thread-read-state-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_get_thread_read_state_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.users.readstate.readonly', ]; // This sample shows how to get the thread read state for a space and calling // user async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME and THREAD_NAME here name: 'users/me/spaces/SPACE_NAME/threads/THREAD_NAME/threadReadState', }; // Make the request const response = await chatClient.getThreadReadState(request); // Handle the response console.log(response); } await main(); // [END chat_get_thread_read_state_user_cred] ================================================ FILE: chat/client-libraries/cloud/list-custom-emojis-user-cred.js ================================================ /** * Copyright 2025 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_list_custom_emojis_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.customemojis', ]; // This sample shows how to get custom emoji with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Optional. Replace FILTER here filter: 'FILTER', }; // Make the request const pageResult = await chatClient.listCustomEmojisAsync(request); // Handle the response. Iterating over pageResult will yield results and // resolve additional pages automatically. for await (const response of pageResult) { console.log(response); } } await main(); // [END chat_list_custom_emojis_user_cred] ================================================ FILE: chat/client-libraries/cloud/list-memberships-app-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_list_memberships_app_cred] import {createClientWithAppCredentials} from './authentication-utils.js'; // This sample shows how to list memberships with app credential async function main() { // Create a client const chatClient = createClientWithAppCredentials(); // Initialize request argument(s) const request = { // Replace SPACE_NAME here parent: 'spaces/SPACE_NAME', // Filter membership by type (HUMAN or BOT) or role (ROLE_MEMBER or // ROLE_MANAGER) filter: 'member.type = "HUMAN"', }; // Make the request const pageResult = chatClient.listMembershipsAsync(request); // Handle the response. Iterating over pageResult will yield results and // resolve additional pages automatically. for await (const response of pageResult) { console.log(response); } } await main(); // [END chat_list_memberships_app_cred] ================================================ FILE: chat/client-libraries/cloud/list-memberships-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_list_memberships_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.memberships.readonly', ]; // This sample shows how to list memberships with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here parent: 'spaces/SPACE_NAME', // Filter membership by type (HUMAN or BOT) or role (ROLE_MEMBER or // ROLE_MANAGER) filter: 'member.type = "HUMAN"', }; // Make the request const pageResult = chatClient.listMembershipsAsync(request); // Handle the response. Iterating over pageResult will yield results and // resolve additional pages automatically. for await (const response of pageResult) { console.log(response); } } await main(); // [END chat_list_memberships_user_cred] ================================================ FILE: chat/client-libraries/cloud/list-messages-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_list_messages_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.messages.readonly', ]; // This sample shows how to list messages with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here parent: 'spaces/SPACE_NAME', }; // Make the request const pageResult = chatClient.listMessagesAsync(request); // Handle the response. Iterating over pageResult will yield results // and resolve additional pages automatically. for await (const response of pageResult) { console.log(response); } } await main(); // [END chat_list_messages_user_cred] ================================================ FILE: chat/client-libraries/cloud/list-reactions-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_list_reactions_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.messages.reactions.readonly', ]; // This sample shows how to list reactions to a message with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME and MESSAGE_NAME here. parent: 'spaces/SPACE_NAME/messages/MESSAGE_NAME', }; // Make the request const pageResult = chatClient.listReactionsAsync(request); // Handle the response. Iterating over pageResult will yield results // and resolve additional pages automatically. for await (const response of pageResult) { console.log(response); } } await main(); // [END chat_list_reactions_user_cred] ================================================ FILE: chat/client-libraries/cloud/list-space-events-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_list_space_events_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; // Authorization scopes based on the event types const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.memberships.readonly', 'https://www.googleapis.com/auth/chat.messages.readonly', ]; // This sample shows how to list space events with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Replace SPACE_NAME here parent: 'spaces/SPACE_NAME', // A required filter. Filters events about new memberships and messages. filter: 'eventTypes:"google.workspace.chat.membership.v1.created" OR eventTypes:"google.workspace.chat.message.v1.created"', }; // Make the request const pageResult = chatClient.listSpaceEventsAsync(request); // Handle the response. Iterating over pageResult will yield results and // resolve additional pages automatically. for await (const response of pageResult) { console.log(response); } } await main(); // [END chat_list_space_events_user_cred] ================================================ FILE: chat/client-libraries/cloud/list-spaces-app-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_list_spaces_app_cred] import {createClientWithAppCredentials} from './authentication-utils.js'; // This sample shows how to list spaces with app credential async function main() { // Create a client const chatClient = createClientWithAppCredentials(); // Initialize request argument(s) const request = { // Filter spaces by space type (SPACE or GROUP_CHAT or DIRECT_MESSAGE) filter: 'space_type = "SPACE"', }; // Make the request const pageResult = chatClient.listSpacesAsync(request); // Handle the response. Iterating over pageResult will yield results // and resolve additional pages automatically. for await (const response of pageResult) { console.log(response); } } await main(); // [END chat_list_spaces_app_cred] ================================================ FILE: chat/client-libraries/cloud/list-spaces-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_list_spaces_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.spaces.readonly', ]; // This sample shows how to list spaces with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { // Filter spaces by space type (SPACE or GROUP_CHAT or DIRECT_MESSAGE) filter: 'space_type = "SPACE"', }; // Make the request const pageResult = chatClient.listSpacesAsync(request); // Handle the response. Iterating over pageResult will yield results // and resolve additional pages automatically. for await (const response of pageResult) { console.log(response); } } await main(); // [END chat_list_spaces_user_cred] ================================================ FILE: chat/client-libraries/cloud/package.json ================================================ { "name": "google-chat-cloud-client-library-samples", "version": "0.0.1", "description": "Samples that use the Cloud client library to call the Google Chat API.", "license": "Apache-2.0", "type": "module", "scripts": { "create-custom-emoji-user-cred.js": "node ./create-custom-emoji-user-cred.js", "create-membership-user-cred-for-app.js": "node ./create-membership-user-cred-for-app.js", "create-membership-user-cred-for-group.js": "node ./create-membership-user-cred-for-group.js", "create-membership-user-cred.js": "node ./create-membership-user-cred.js", "create-message-app-cred.js": "node ./create-message-app-cred.js", "create-message-user-cred-at-mention.js": "node ./create-message-user-cred-at-mention.js", "create-message-user-cred-message-id.js": "node ./create-message-user-cred-message-id.js", "create-message-user-cred-request-id.js": "node ./create-message-user-cred-request-id.js", "create-message-user-cred-thread-key.js": "node ./create-message-user-cred-thread-key.js", "create-message-user-cred-thread-name.js": "node ./create-message-user-cred-thread-name.js", "create-message-user-cred.js": "node ./create-message-user-cred.js", "create-reaction-user-cred.js": "node ./create-reaction-user-cred.js", "create-space-user-cred.js": "node ./create-space-user-cred.js", "delete-custom-emoji-user-cred.js": "node ./delete-custom-emoji-user-cred.js", "delete-membership-user-cred.js": "node ./delete-membership-user-cred.js", "delete-message-app-cred.js": "node ./delete-message-app-cred.js", "delete-message-user-cred.js": "node ./delete-message-user-cred.js", "delete-reaction-user-cred.js": "node ./delete-reaction-user-cred.js", "delete-space-user-cred.js": "node ./delete-space-user-cred.js", "find-dm-space-app-cred.js": "node ./find-dm-space-app-cred.js", "find-dm-space-user-cred.js": "node ./find-dm-space-user-cred.js", "get-attachment-app-cred.js": "node ./get-attachment-app-cred.js", "get-custom-emoji-user-cred.js": "node ./get-custom-emoji-user-cred.js", "get-membership-app-cred.js": "node ./get-membership-app-cred.js", "get-membership-user-cred.js": "node ./get-membership-user-cred.js", "get-message-app-cred.js": "node ./get-message-app-cred.js", "get-message-user-cred.js": "node ./get-message-user-cred.js", "get-space-app-cred.js": "node ./get-space-app-cred.js", "get-space-event-user-cred.js": "node ./get-space-event-user-cred.js", "get-space-notification-setting-user-cred.js": "node ./get-space-notification-setting-user-cred.js", "get-space-read-state-user-cred.js": "node ./get-space-read-state-user-cred.js", "get-space-user-cred.js": "node ./get-space-user-cred.js", "get-thread-read-state-user-cred.js": "node ./get-thread-read-state-user-cred.js", "list-custom-emojis-user-cred.js": "node ./list-custom-emojis-user-cred.js", "list-memberships-app-cred.js": "node ./list-memberships-app-cred.js", "list-memberships-user-cred.js": "node ./list-memberships-user-cred.js", "list-messages-user-cred.js": "node ./list-messages-user-cred.js", "list-reactions-user-cred.js": "node ./list-reactions-user-cred.js", "list-space-events-user-cred.js": "node ./list-space-events-user-cred.js", "list-spaces-app-cred.js": "node ./list-spaces-app-cred.js", "list-spaces-user-cred.js": "node ./list-spaces-user-cred.js", "set-up-space-user-cred.js": "node ./set-up-space-user-cred.js", "update-membership-user-cred.js": "node ./update-membership-user-cred.js", "update-message-app-cred.js": "node ./update-message-app-cred.js", "update-message-user-cred.js": "node ./update-message-user-cred.js", "update-space-notification-setting-user-cred.js": "node ./update-space-notification-setting-user-cred.js", "update-space-read-state-user-cred.js": "node ./update-space-read-state-user-cred.js", "update-space-user-cred.js": "node ./update-space-user-cred.js" }, "dependencies": { "@google-apps/chat": "catalog:", "@grpc/grpc-js": "catalog:", "open": "catalog:", "server-destroy": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: chat/client-libraries/cloud/set-up-space-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_set_up_space_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.spaces.create', ]; // This sample shows how to set up a named space with one initial member // with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { space: { spaceType: 'SPACE', // Replace DISPLAY_NAME here. displayName: 'DISPLAY_NAME', }, memberships: [ { member: { // Replace USER_NAME here. name: 'users/USER_NAME', type: 'HUMAN', }, }, ], }; // Make the request const response = await chatClient.setUpSpace(request); // Handle the response console.log(response); } await main(); // [END chat_set_up_space_user_cred] ================================================ FILE: chat/client-libraries/cloud/tsconfig.json ================================================ { "extends": "../../../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: chat/client-libraries/cloud/update-membership-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_update_membership_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.memberships', ]; // This sample shows how to update a membership with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { membership: { // Replace SPACE_NAME and MEMBER_NAME here name: 'spaces/SPACE_NAME/members/MEMBER_NAME', // Replace ROLE_NAME here with ROLE_MEMBER or ROLE_MANAGER role: 'ROLE_NAME', }, updateMask: { // The field paths to update. paths: ['role'], }, }; // Make the request const response = await chatClient.updateMembership(request); // Handle the response console.log(response); } await main(); // [END chat_update_membership_user_cred] ================================================ FILE: chat/client-libraries/cloud/update-message-app-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_update_message_app_cred] import {createClientWithAppCredentials} from './authentication-utils.js'; // This sample shows how to update a message with app credential async function main() { // Create a client const chatClient = createClientWithAppCredentials(); // Initialize request argument(s) const request = { message: { // Replace SPACE_NAME and MESSAGE_NAME here name: 'spaces/SPACE_NAME/messages/MESSAGE_NAME', text: 'Text updated with app credential!', cardsV2: [ { card: { header: { title: 'Card updated with app credential!', imageUrl: 'https://fonts.gstatic.com/s/i/short-term/release/googlesymbols/info/default/24px.svg', }, }, }, ], }, // The field paths to update. Separate multiple values with commas or use `*` // to update all field paths. updateMask: { // The field paths to update. paths: ['text', 'cards_v2'], }, }; // Make the request const response = await chatClient.updateMessage(request); // Handle the response console.log(response); } await main(); // [END chat_update_message_app_cred] ================================================ FILE: chat/client-libraries/cloud/update-message-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_update_message_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.messages', ]; // This sample shows how to update a message with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { message: { // Replace SPACE_NAME and MESSAGE_NAME here name: 'spaces/SPACE_NAME/messages/MESSAGE_NAME', text: 'Updated with user credential!', }, // The field paths to update. Separate multiple values with commas or use `*` // to update all field paths. updateMask: { // The field paths to update. paths: ['text'], }, }; // Make the request const response = await chatClient.updateMessage(request); // Handle the response console.log(response); } await main(); // [END chat_update_message_user_cred] ================================================ FILE: chat/client-libraries/cloud/update-space-notification-setting-user-cred.js ================================================ /** * Copyright 2025 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_update_space_notification_setting_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.users.spacesettings', ]; // This sample shows how to update the space notification setting for the // calling user async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s), replace the SPACE_NAME with an actual space // name. const request = { spaceNotificationSetting: { name: 'users/me/spaces/SPACE_NAME/spaceNotificationSetting', notificationSetting: 'ALL', muteSetting: 'UNMUTED', }, updateMask: {paths: ['notification_setting', 'mute_setting']}, }; // Make the request const response = await chatClient.updateSpaceNotificationSetting(request); // Handle the response console.log(response); } await main(); // [END chat_update_space_notification_setting_user_cred] ================================================ FILE: chat/client-libraries/cloud/update-space-read-state-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_update_space_read_state_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = [ 'https://www.googleapis.com/auth/chat.users.readstate', ]; // This sample shows how to update a space read state for the calling user async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const timestamp = new Date('2000-01-01').getTime(); const request = { spaceReadState: { // Replace SPACE_NAME here name: 'users/me/spaces/SPACE_NAME/spaceReadState', lastReadTime: { seconds: Math.floor(timestamp / 1000), nanos: (timestamp % 1000) * 1000000, }, }, updateMask: { // The field paths to update. paths: ['last_read_time'], }, }; // Make the request const response = await chatClient.updateSpaceReadState(request); // Handle the response console.log(response); } await main(); // [END chat_update_space_read_state_user_cred] ================================================ FILE: chat/client-libraries/cloud/update-space-user-cred.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // It may require modifications to work in your environment. // [START chat_update_space_user_cred] import {createClientWithUserCredentials} from './authentication-utils.js'; const USER_AUTH_OAUTH_SCOPES = ['https://www.googleapis.com/auth/chat.spaces']; // This sample shows how to update a space with user credential async function main() { // Create a client const chatClient = await createClientWithUserCredentials( USER_AUTH_OAUTH_SCOPES, ); // Initialize request argument(s) const request = { space: { // Replace SPACE_NAME here name: 'spaces/SPACE_NAME', displayName: 'New space display name', }, // The field paths to update. Separate multiple values with commas or use `*` // to update all field paths. updateMask: { // The field paths to update. paths: ['display_name'], }, }; // Make the request const response = await chatClient.updateSpace(request); // Handle the response console.log(response); } await main(); // [END chat_update_space_user_cred] ================================================ FILE: chat/quickstart/index.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START chat_quickstart] import path from 'node:path'; import process from 'node:process'; import {ChatServiceClient} from '@google-apps/chat'; import {authenticate} from '@google-cloud/local-auth'; // The scope for reading Chat spaces. const SCOPES = ['https://www.googleapis.com/auth/chat.spaces.readonly']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Lists the spaces that the user is a member of. */ async function listSpaces() { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Chat API client. const chatClient = new ChatServiceClient({ authClient, scopes: SCOPES, }); // The request to list spaces. const request = { // Filter spaces by type. In this case, we are only interested in "SPACE" type. filter: 'space_type = "SPACE"', }; // Make the API request. const pageResult = chatClient.listSpacesAsync(request); // Process the response. // The `pageResult` is an async iterable that will yield each space. for await (const response of pageResult) { console.log(response); } } await listSpaces(); // [END chat_quickstart] ================================================ FILE: chat/quickstart/package.json ================================================ { "name": "google-chat-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google Chat API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-apps/chat": "catalog:", "@google-cloud/local-auth": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: chat/quickstart/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: classroom/quickstart/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START classroom_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; // The scope for reading Classroom courses. const SCOPES = ['https://www.googleapis.com/auth/classroom.courses.readonly']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Lists the first 10 courses the user has access to. */ async function listCourses() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Classroom API client. const classroom = google.classroom({version: 'v1', auth}); // Get the list of courses. const result = await classroom.courses.list({ pageSize: 10, }); const courses = result.data.courses; if (!courses || courses.length === 0) { console.log('No courses found.'); return; } console.log('Courses:'); // Print the name and ID of each course. courses.forEach((course) => { console.log(`${course.name} (${course.id})`); }); } await listCourses(); // [END classroom_quickstart] ================================================ FILE: classroom/quickstart/package.json ================================================ { "name": "google-classroom-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google Classroom API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: classroom/quickstart/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: docs/quickstart/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START docs_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; // The scope for reading Google Docs. const SCOPES = ['https://www.googleapis.com/auth/documents.readonly']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Prints the title of a sample doc: * https://docs.google.com/document/d/195j9eDD3ccgjQRttHhJPymLJUCOUjs-jmwTrekvdjFE/edit */ async function printDocTitle() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Docs API client. const docs = google.docs({version: 'v1', auth}); // Get the document. const result = await docs.documents.get({ documentId: '195j9eDD3ccgjQRttHhJPymLJUCOUjs-jmwTrekvdjFE', }); // Print the title of the document. console.log(`The title of the document is: ${result.data.title}`); } await printDocTitle(); // [END docs_quickstart] ================================================ FILE: docs/quickstart/package.json ================================================ { "name": "docs-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Docs API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: docs/quickstart/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: drive/activity-v2/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_activity_v2_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; // The scope for reading Drive activity. const SCOPES = ['https://www.googleapis.com/auth/drive.activity.readonly']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Lists the recent activity in your Google Drive. */ async function listDriveActivity() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Drive Activity API client. const service = google.driveactivity({version: 'v2', auth}); // The parameters for the activity query. const params = { pageSize: 10, }; // Query for recent activity. const result = await service.activity.query({requestBody: params}); const activities = result.data.activities; if (!activities || activities.length === 0) { console.log('No activity.'); return; } console.log('Recent activity:'); // Print the recent activity. console.log(JSON.stringify(activities, null, 2)); } await listDriveActivity(); // [END drive_activity_v2_quickstart] ================================================ FILE: drive/activity-v2/package.json ================================================ { "name": "google-drive-activity-v2-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google Drive Activity v2 API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: drive/activity-v2/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: drive/quickstart/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; // The scope for reading file metadata. const SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Lists the names and IDs of up to 10 files. */ async function listFiles() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Drive API client. const drive = google.drive({version: 'v3', auth}); // Get the list of files. const result = await drive.files.list({ pageSize: 10, fields: 'nextPageToken, files(id, name)', }); const files = result.data.files; if (!files || files.length === 0) { console.log('No files found.'); return; } console.log('Files:'); // Print the name and ID of each file. files.forEach((file) => { console.log(`${file.name} (${file.id})`); }); } await listFiles(); // [END drive_quickstart] ================================================ FILE: drive/quickstart/package.json ================================================ { "name": "google-drive-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google Drive API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: drive/quickstart/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: drive/snippets/drive_v2/appdata_snippets/fetch_appdata_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_fetch_appdata_folder] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Fetches the ID of the application data folder. * @return {Promise} The ID of the application data folder. */ async function fetchAppdataFolder() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive.appdata', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // Get the application data folder. const file = await service.files.get({ fileId: 'appDataFolder', fields: 'id', }); // Print the folder ID. console.log('File Id:', file.data.id); if (!file.data.id) { throw new Error('File ID not found.'); } return file.data.id; } // [END drive_fetch_appdata_folder] export {fetchAppdataFolder}; ================================================ FILE: drive/snippets/drive_v2/appdata_snippets/list_appdata.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_list_appdata] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Lists all files in the application data folder. * @return {Promise} A list of files. */ async function listAppdata() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive.appdata', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // List the files in the application data folder. const result = await service.files.list({ spaces: 'appDataFolder', fields: 'nextPageToken, items(id, title)', maxResults: 100, }); // Print the title and ID of each file. (result.data.items ?? []).forEach((file) => { console.log('Found file:', file.title, file.id); }); return result.data.items ?? []; } // [END drive_list_appdata] export {listAppdata}; ================================================ FILE: drive/snippets/drive_v2/appdata_snippets/package.json ================================================ { "name": "drive-snippets-drive-v2-appdata-snippets", "version": "1.0.0", "private": true, "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" }, "dependencies": { "googleapis": "catalog:" } } ================================================ FILE: drive/snippets/drive_v2/appdata_snippets/tsconfig.json ================================================ { "extends": "../../../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: drive/snippets/drive_v2/appdata_snippets/upload_appdata.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_upload_appdata] import fs from 'node:fs'; import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Uploads a file to the application data folder. * @return {Promise} The ID of the uploaded file. */ async function uploadAppdata() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive.appdata', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // The metadata for the file to be uploaded. const fileMetadata = { title: 'config.json', parents: [ { id: 'appDataFolder', }, ], }; // The media content to be uploaded. const media = { mimeType: 'application/json', body: fs.createReadStream('files/config.json'), }; // Upload the file to the application data folder. const file = await service.files.insert({ requestBody: fileMetadata, media, fields: 'id', }); // Print the ID of the uploaded file. console.log('File Id:', file.data.id); if (!file.data.id) { throw new Error('File ID not found.'); } return file.data.id; } // [END drive_upload_appdata] export {uploadAppdata}; ================================================ FILE: drive/snippets/drive_v2/change_snippets/fetch_changes.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_fetch_changes] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Fetches the list of changes for the currently authenticated user. * @return {Promise} A list of changes. */ async function fetchChanges() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // The page token for the next page of changes. If not set, the first page is retrieved. let pageToken; // Fetch the list of changes. const result = await service.changes.list({ pageToken, fields: '*', }); // Process the changes. (result.data.items ?? []).forEach((change) => { console.log('Change found for file:', change.fileId); }); return result.data.items ?? []; } // [END drive_fetch_changes] export {fetchChanges}; ================================================ FILE: drive/snippets/drive_v2/change_snippets/fetch_start_page_token.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_fetch_start_page_token] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Fetches the start page token for the current state of the user's account. * @return {Promise} The start page token. */ async function fetchStartPageToken() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // Fetch the start page token. const result = await service.changes.getStartPageToken(); console.log('Start token:', result.data.startPageToken); if (!result.data.startPageToken) { throw new Error('Start page token not found.'); } return result.data.startPageToken; } // [END drive_fetch_start_page_token] export {fetchStartPageToken}; ================================================ FILE: drive/snippets/drive_v2/change_snippets/package.json ================================================ { "name": "drive-snippets-drive-v2-change-snippets", "version": "1.0.0", "private": true, "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" }, "dependencies": { "googleapis": "catalog:" } } ================================================ FILE: drive/snippets/drive_v2/change_snippets/tsconfig.json ================================================ { "extends": "../../../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: drive/snippets/drive_v2/drive_snippets/create_drive.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_create_drive] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; import {v4 as uuid} from 'uuid'; /** * Creates a new shared drive. * @return {Promise} The ID of the created shared drive. */ async function createDrive() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // The metadata for the new shared drive. const driveMetadata = { name: 'Project resources', }; // A unique request ID to avoid creating duplicate shared drives. const requestId = uuid(); // Create the new shared drive. const Drive = await service.drives.insert({ requestBody: driveMetadata, requestId, fields: 'id', }); // Print the ID of the new shared drive. console.log('Drive Id:', Drive.data.id); if (!Drive.data.id) { throw new Error('Drive ID not found.'); } return Drive.data.id; } // [END drive_create_drive] export {createDrive}; ================================================ FILE: drive/snippets/drive_v2/drive_snippets/package.json ================================================ { "name": "drive-snippets-drive-v2-drive-snippets", "version": "1.0.0", "private": true, "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "devDependencies": { "@types/uuid": "catalog:", "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" }, "dependencies": { "googleapis": "catalog:" } } ================================================ FILE: drive/snippets/drive_v2/drive_snippets/recover_drives.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_recover_drives] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Finds all shared drives without an organizer and adds one. * @param {string} userEmail The email of the user to make an organizer. */ async function recoverDrives(userEmail) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // The permission to add to the shared drive. const newOrganizerPermission = { type: 'user', role: 'organizer', value: userEmail, }; // List all shared drives with no organizers. const result = await service.drives.list({ q: 'organizerCount = 0', fields: 'nextPageToken, items(id, name)', useDomainAdminAccess: true, }); // Add the new organizer to each found shared drive. for (const drive of result.data.items ?? []) { if (!drive.id) { continue; } console.log('Found shared drive without organizer:', drive.name, drive.id); await service.permissions.insert({ requestBody: newOrganizerPermission, fileId: drive.id, useDomainAdminAccess: true, supportsAllDrives: true, fields: 'id', }); } } // [END drive_recover_drives] export {recoverDrives}; ================================================ FILE: drive/snippets/drive_v2/drive_snippets/tsconfig.json ================================================ { "extends": "../../../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: drive/snippets/drive_v2/file snippets/create_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_create_folder] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Creates a new folder in Google Drive. * @return {Promise} The ID of the created folder. */ async function createFolder() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // The metadata for the new folder. const fileMetadata = { title: 'Invoices', mimeType: 'application/vnd.google-apps.folder', }; // Create the new folder. const file = await service.files.insert({ requestBody: fileMetadata, fields: 'id', }); // Print the ID of the new folder. console.log('Folder Id:', file.data.id); if (!file.data.id) { throw new Error('File ID not found.'); } return file.data.id; } // [END drive_create_folder] export {createFolder}; ================================================ FILE: drive/snippets/drive_v2/file snippets/create_shortcut.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_create_shortcut] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Creates a shortcut to a third-party resource. * @return {Promise} The ID of the created shortcut. */ async function createShortcut() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // The metadata for the new shortcut. const fileMetadata = { title: 'Project plan', mimeType: 'application/vnd.google-apps.drive-sdk', }; // Create the new shortcut. const file = await service.files.insert({ requestBody: fileMetadata, fields: 'id', }); // Print the ID of the new shortcut. console.log('File Id:', file.data.id); if (!file.data.id) { throw new Error('File ID not found.'); } return file.data.id; } // [END drive_create_shortcut] export {createShortcut}; ================================================ FILE: drive/snippets/drive_v2/file snippets/download_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_download_file] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Downloads a file from Google Drive. * @param {string} fileId The ID of the file to download. * @return {Promise} The status of the download. */ async function downloadFile(fileId) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // Download the file. const file = await service.files.get({ fileId, alt: 'media', }); // Print the status of the download. console.log(file.status); return file.status; } // [END drive_download_file] export {downloadFile}; ================================================ FILE: drive/snippets/drive_v2/file snippets/export_pdf.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_export_pdf] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Exports a Google Doc as a PDF. * @param {string} fileId The ID of the file to export. * @return {Promise} The response from the export request. */ async function exportPdf(fileId) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // Export the file as a PDF. const result = await service.files.export({ fileId, mimeType: 'application/pdf', }); // Print the status of the export. console.log(result.status); return result; } // [END drive_export_pdf] export {exportPdf}; ================================================ FILE: drive/snippets/drive_v2/file snippets/move_file_to_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_move_file_to_folder] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Moves a file to a new folder in Google Drive. * @param {string} fileId The ID of the file to move. * @param {string} folderId The ID of the folder to move the file to. * @return {Promise} The status of the move operation. */ async function moveFileToFolder(fileId, folderId) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // Get the file's metadata to retrieve its current parents. const file = await service.files.get({ fileId, fields: 'parents', }); // Get the current parents as a comma-separated string. const previousParents = (file.data.parents ?? []) .map((parent) => parent.id) .join(','); // Move the file to the new folder. const files = await service.files.update({ fileId, addParents: folderId, removeParents: previousParents, fields: 'id, parents', }); // Print the status of the move operation. console.log(files.status); return files.status; } // [END drive_move_file_to_folder] export {moveFileToFolder}; ================================================ FILE: drive/snippets/drive_v2/file snippets/package.json ================================================ { "name": "drive-snippets-drive-v2-file-snippets", "version": "1.0.0", "private": true, "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" }, "dependencies": { "googleapis": "catalog:" } } ================================================ FILE: drive/snippets/drive_v2/file snippets/search_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_search_file] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Searches for files in Google Drive. * @return {Promise} A list of files. */ async function searchFile() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // The page token for the next page of results. If not set, the first page is retrieved. const pageToken = undefined; // Search for files with the specified query. const result = await service.files.list({ q: "mimeType='image/jpeg'", fields: 'nextPageToken, items(id, title)', spaces: 'drive', pageToken, }); // Print the title and ID of each found file. (result.data.items ?? []).forEach((file) => { console.log('Found file:', file.title, file.id); }); return result.data.items ?? []; } // [END drive_search_file] export {searchFile}; ================================================ FILE: drive/snippets/drive_v2/file snippets/share_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_share_file] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Shares a file with a user and a domain. * @param {string} fileId The ID of the file to share. * @param {string} targetUser The email address of the user to share with. * @param {string} targetDomain The domain to share with. * @return {Promise} A list of the inserted permission IDs. */ async function shareFile(fileId, targetUser, targetDomain) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); const permissionIds = []; // The permissions to insert. const permissions = [ { type: 'user', role: 'writer', value: targetUser, // e.g., 'user@example.com' }, { type: 'domain', role: 'writer', value: targetDomain, // e.g., 'example.com' }, ]; // Note: The client library does not currently support batch requests for permissions. // When possible, use batch requests to insert multiple permissions on the same item. for (const permission of permissions) { // Insert the permission. const result = await service.permissions.insert({ requestBody: permission, fileId, fields: 'id', }); if (result.data.id) { permissionIds.push(result.data.id); console.log(`Inserted permission id: ${result.data.id}`); } else { throw new Error('Failed to create permission'); } } return permissionIds; } // [END drive_share_file] export {shareFile}; ================================================ FILE: drive/snippets/drive_v2/file snippets/touch_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_touch_file] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Updates the modification timestamp of a file. * @param {string} fileId The ID of the file to update. * @param {string} timestamp The new modification timestamp. * @return {Promise} The updated modification timestamp. */ async function touchFile(fileId, timestamp) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // The metadata to update. const fileMetadata = { modifiedDate: new Date().toISOString(), modifiedTime: timestamp, }; // Update the file's modification timestamp. const file = await service.files.update({ fileId, setModifiedDate: true, requestBody: fileMetadata, fields: 'id, modifiedDate', }); // Print the new modification timestamp. console.log('Modified time:', file.data.modifiedDate); return file.data.modifiedDate; } // [END drive_touch_file] export {touchFile}; ================================================ FILE: drive/snippets/drive_v2/file snippets/tsconfig.json ================================================ { "extends": "../../../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: drive/snippets/drive_v2/file snippets/upload_basic.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_upload_basic] import fs from 'node:fs'; import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Uploads a file to Google Drive. * @return {Promise} The ID of the uploaded file. */ async function uploadBasic() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // The metadata for the file to be uploaded. const fileMetadata = { title: 'photo.jpg', }; // The media content to be uploaded. const media = { mimeType: 'image/jpeg', body: fs.createReadStream('files/photo.jpg'), }; // Upload the file. const file = await service.files.insert({ requestBody: fileMetadata, media, fields: 'id', }); // Print the ID of the uploaded file. console.log('File Id:', file.data.id); if (!file.data.id) { throw new Error('File ID not found.'); } return file.data.id; } // [END drive_upload_basic] export {uploadBasic}; ================================================ FILE: drive/snippets/drive_v2/file snippets/upload_to_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_upload_to_folder] import fs from 'node:fs'; import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Uploads a file to a specific folder in Google Drive. * @param {string} folderId The ID of the folder to upload the file to. * @return {Promise} The ID of the uploaded file. */ async function uploadToFolder(folderId) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // The metadata for the file to be uploaded. const fileMetadata = { title: 'photo.jpg', parents: [{id: folderId}], }; // The media content to be uploaded. const media = { mimeType: 'image/jpeg', body: fs.createReadStream('files/photo.jpg'), }; // Upload the file to the specified folder. const file = await service.files.insert({ requestBody: fileMetadata, media, fields: 'id', }); // Print the ID of the uploaded file. console.log('File Id:', file.data.id); if (!file.data.id) { throw new Error('File ID not found.'); } return file.data.id; } // [END drive_upload_to_folder] export {uploadToFolder}; ================================================ FILE: drive/snippets/drive_v2/file snippets/upload_with_conversion.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_upload_with_conversion] import fs from 'node:fs'; import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Uploads a file to Google Drive and converts it to a Google Sheet. * @return {Promise} The ID of the uploaded file. */ async function uploadWithConversion() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // The metadata for the file to be uploaded and converted. const fileMetadata = { title: 'My Report', // The MIME type to convert the file to. mimeType: 'application/vnd.google-apps.spreadsheet', }; // The media content to be uploaded. const media = { mimeType: 'text/csv', body: fs.createReadStream('files/report.csv'), }; // Upload the file with conversion. const file = await service.files.insert({ requestBody: fileMetadata, media, fields: 'id', }); // Print the ID of the uploaded file. console.log('File Id:', file.data.id); if (!file.data.id) { throw new Error('File ID not found.'); } return file.data.id; } // [END drive_upload_with_conversion] export {uploadWithConversion}; ================================================ FILE: drive/snippets/drive_v3/appdata_snippets/fetch_appdata_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_fetch_appdata_folder] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Fetches the ID of the application data folder. * @return {Promise} The ID of the application data folder. */ async function fetchAppdataFolder() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive.appdata', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // Get the application data folder. const file = await service.files.get({ fileId: 'appDataFolder', fields: 'id', }); // Print the folder ID. console.log('File Id:', file.data.id); if (!file.data.id) { throw new Error('File ID not found.'); } return file.data.id; } // [END drive_fetch_appdata_folder] export {fetchAppdataFolder}; ================================================ FILE: drive/snippets/drive_v3/appdata_snippets/list_appdata.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_list_appdata] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Lists all files in the application data folder. * @return {Promise} A list of files. */ async function listAppdata() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive.appdata', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // List the files in the application data folder. const result = await service.files.list({ spaces: 'appDataFolder', fields: 'nextPageToken, files(id, name)', pageSize: 100, }); // Print the name and ID of each file. (result.data.files ?? []).forEach((file) => { console.log('Found file:', file.name, file.id); }); return result.data.files ?? []; } // [END drive_list_appdata] export {listAppdata}; ================================================ FILE: drive/snippets/drive_v3/appdata_snippets/package.json ================================================ { "name": "drive-snippets-drive-v3-appdata-snippets", "version": "1.0.0", "private": true, "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" }, "dependencies": { "googleapis": "catalog:" } } ================================================ FILE: drive/snippets/drive_v3/appdata_snippets/tsconfig.json ================================================ { "extends": "../../../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: drive/snippets/drive_v3/appdata_snippets/upload_appdata.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_upload_appdata] import fs from 'node:fs'; import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Uploads a file to the application data folder. * @return {Promise} The ID of the uploaded file. */ async function uploadAppdata() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive.appdata', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // The metadata for the file to be uploaded. const fileMetadata = { name: 'config.json', parents: ['appDataFolder'], }; // The media content to be uploaded. const media = { mimeType: 'application/json', body: fs.createReadStream('files/config.json'), }; // Upload the file to the application data folder. const file = await service.files.create({ requestBody: fileMetadata, media, fields: 'id', }); // Print the ID of the uploaded file. console.log('File Id:', file.data.id); if (!file.data.id) { throw new Error('File ID not found.'); } return file.data.id; } // [END drive_upload_appdata] export {uploadAppdata}; ================================================ FILE: drive/snippets/drive_v3/change_snippets/fetch_changes.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_fetch_changes] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Fetches the list of changes for the currently authenticated user. * @param {string} savedStartPageToken The page token obtained from `fetch_start_page_token.js`. */ async function fetchChanges(savedStartPageToken) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive.readonly', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // The page token for the next page of changes. let pageToken = savedStartPageToken; // Loop to fetch all changes, handling pagination. do { const result = await service.changes.list({ pageToken: savedStartPageToken, fields: '*', }); // Process the changes. (result.data.changes ?? []).forEach((change) => { console.log('change found for file: ', change.fileId); }); // Update the page token for the next iteration. pageToken = result.data.newStartPageToken ?? ''; } while (pageToken); } // [END drive_fetch_changes] export {fetchChanges}; ================================================ FILE: drive/snippets/drive_v3/change_snippets/fetch_start_page_token.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_fetch_start_page_token] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Fetches the start page token for the current state of the account. * @return {Promise} The start page token. */ async function fetchStartPageToken() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive.appdata', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // Fetch the start page token. const res = await service.changes.getStartPageToken({}); const token = res.data.startPageToken; console.log('start token: ', token); if (!token) { throw new Error('Start page token not found.'); } return token; } // [END drive_fetch_start_page_token] export {fetchStartPageToken}; ================================================ FILE: drive/snippets/drive_v3/change_snippets/package.json ================================================ { "name": "drive-snippets-drive-v3-change-snippets", "version": "1.0.0", "private": true, "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" }, "dependencies": { "googleapis": "catalog:" } } ================================================ FILE: drive/snippets/drive_v3/change_snippets/tsconfig.json ================================================ { "extends": "../../../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: drive/snippets/drive_v3/drive_snippets/create_drive.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_create_drive] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; import {v4 as uuid} from 'uuid'; /** * Creates a new shared drive. * @return {Promise} The ID of the created shared drive. */ async function createDrive() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // The metadata for the new shared drive. const driveMetadata = { name: 'Project resources', }; // A unique request ID to avoid creating duplicate shared drives. const requestId = uuid(); // Create the new shared drive. const Drive = await service.drives.create({ requestBody: driveMetadata, requestId, fields: 'id', }); // Print the ID of the new shared drive. console.log('Drive Id:', Drive.data.id); if (!Drive.data.id) { throw new Error('Drive ID not found.'); } return Drive.data.id; } // [END drive_create_drive] export {createDrive}; ================================================ FILE: drive/snippets/drive_v3/drive_snippets/package.json ================================================ { "name": "drive-snippets-drive-v3-drive-snippets", "version": "1.0.0", "private": true, "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "devDependencies": { "@types/uuid": "catalog:", "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" }, "dependencies": { "googleapis": "catalog:" } } ================================================ FILE: drive/snippets/drive_v3/drive_snippets/recover_drives.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_recover_drives] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Finds all shared drives without an organizer and adds one. * @param {string} userEmail The email of the user to assign ownership to. * @return {Promise} A list of the recovered drives. */ async function recoverDrives(userEmail) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // The permission to add to the shared drive. const newOrganizerPermission = { type: 'user', role: 'organizer', emailAddress: userEmail, // e.g., 'user@example.com' }; // List all shared drives with no organizers. const result = await service.drives.list({ q: 'organizerCount = 0', fields: 'nextPageToken, drives(id, name)', useDomainAdminAccess: true, }); // Add the new organizer to each found shared drive. for (const drive of result.data.drives ?? []) { if (!drive.id) { continue; } console.log('Found shared drive without organizer:', drive.name, drive.id); await service.permissions.create({ requestBody: newOrganizerPermission, fileId: drive.id, useDomainAdminAccess: true, supportsAllDrives: true, fields: 'id', }); } return result.data.drives ?? []; } // [END drive_recover_drives] export {recoverDrives}; ================================================ FILE: drive/snippets/drive_v3/drive_snippets/tsconfig.json ================================================ { "extends": "../../../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: drive/snippets/drive_v3/file_snippets/create_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_create_folder] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Creates a new folder in Google Drive. * @return {Promise} The ID of the created folder. */ async function createFolder() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // The metadata for the new folder. const fileMetadata = { name: 'Invoices', mimeType: 'application/vnd.google-apps.folder', }; // Create the new folder. const file = await service.files.create({ requestBody: fileMetadata, fields: 'id', }); // Print the ID of the new folder. console.log('Folder Id:', file.data.id); return file.data.id; } // [END drive_create_folder] export {createFolder}; ================================================ FILE: drive/snippets/drive_v3/file_snippets/create_shortcut.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_create_shortcut] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Creates a shortcut to a third-party resource. * @return {Promise} The shortcut ID. */ async function createShortcut() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // The metadata for the new shortcut. const fileMetadata = { name: 'Project plan', mimeType: 'application/vnd.google-apps.drive-sdk', }; // Create the new shortcut. const file = await service.files.create({ requestBody: fileMetadata, fields: 'id', }); // Print the ID of the new shortcut. console.log('File Id:', file.data.id); return file.data.id; } // [END drive_create_shortcut] export {createShortcut}; ================================================ FILE: drive/snippets/drive_v3/file_snippets/download_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_download_file] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Downloads a file from Google Drive. * @param {string} fileId The ID of the file to download. * @return {Promise} The status of the download. */ async function downloadFile(fileId) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // Download the file. const file = await service.files.get({ fileId, alt: 'media', }); // Print the status of the download. console.log(file.status); return file.status; } // [END drive_download_file] export {downloadFile}; ================================================ FILE: drive/snippets/drive_v3/file_snippets/export_pdf.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_export_pdf] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Exports a Google Doc as a PDF. * @param {string} fileId The ID of the file to export. * @return {Promise} The status of the export request. */ async function exportPdf(fileId) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // Export the file as a PDF. const result = await service.files.export({ fileId, mimeType: 'application/pdf', }); // Print the status of the export. console.log(result.status); return result.status; } // [END drive_export_pdf] export {exportPdf}; ================================================ FILE: drive/snippets/drive_v3/file_snippets/move_file_to_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_move_file_to_folder] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Moves a file to a new folder in Google Drive. * @param {string} fileId The ID of the file to move. * @param {string} folderId The ID of the folder to move the file to. * @return {Promise} The status of the move operation. */ async function moveFileToFolder(fileId, folderId) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // Get the file's metadata to retrieve its current parents. const file = await service.files.get({ fileId, fields: 'parents', }); // Get the current parents as a comma-separated string. const previousParents = (file.data.parents ?? []).join(','); // Move the file to the new folder. const result = await service.files.update({ fileId, addParents: folderId, removeParents: previousParents, fields: 'id, parents', }); // Print the status of the move operation. console.log(result.status); return result.status; } // [END drive_move_file_to_folder] export {moveFileToFolder}; ================================================ FILE: drive/snippets/drive_v3/file_snippets/package.json ================================================ { "name": "drive-snippets-drive-v3-file-snippets", "version": "1.0.0", "private": true, "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" }, "dependencies": { "googleapis": "catalog:" } } ================================================ FILE: drive/snippets/drive_v3/file_snippets/search_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_search_file] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Searches for files in Google Drive. * @return {Promise} A list of files. */ async function searchFile() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // Search for files with the specified query. const result = await service.files.list({ q: "mimeType='image/jpeg'", fields: 'nextPageToken, files(id, name)', spaces: 'drive', }); // Print the name and ID of each found file. (result.data.files ?? []).forEach((file) => { console.log('Found file:', file.name, file.id); }); return result.data.files ?? []; } // [END drive_search_file] export {searchFile}; ================================================ FILE: drive/snippets/drive_v3/file_snippets/share_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_share_file] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Shares a file with a user and a domain. * @param {string} fileId The ID of the file to share. * @param {string} targetUserEmail The email address of the user to share with. * @param {string} targetDomainName The domain to share with. * @return {Promise>} A promise that resolves to an array of permission IDs. */ async function shareFile(fileId, targetUserEmail, targetDomainName) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); /** @type {Array} */ const permissionIds = []; // The permissions to create. const permissions = [ { type: 'user', role: 'writer', emailAddress: targetUserEmail, // e.g., 'user@partner.com' }, { type: 'domain', role: 'writer', domain: targetDomainName, // e.g., 'example.com' }, ]; // Iterate through the permissions and create them one by one. for (const permission of permissions) { const result = await service.permissions.create({ requestBody: permission, fileId, fields: 'id', }); if (result.data.id) { permissionIds.push(result.data.id); console.log(`Inserted permission id: ${result.data.id}`); } else { throw new Error('Failed to create permission'); } } return permissionIds; } // [END drive_share_file] export {shareFile}; ================================================ FILE: drive/snippets/drive_v3/file_snippets/touch_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_touch_file] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Updates the modification timestamp of a file. * @param {string} fileId The ID of the file to update. * @param {string} timestamp The new modification timestamp. * @return {Promise} The modified timestamp. */ async function touchFile(fileId, timestamp) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // The metadata to update. const fileMetadata = { modifiedTime: new Date().toISOString(), }; fileMetadata.modifiedTime = timestamp; // Update the file's modification timestamp. const file = await service.files.update({ fileId, requestBody: fileMetadata, fields: 'id, modifiedTime', }); // Print the new modification timestamp. console.log('Modified time:', file.data.modifiedTime); return file.data.modifiedTime; } // [END drive_touch_file] export {touchFile}; ================================================ FILE: drive/snippets/drive_v3/file_snippets/tsconfig.json ================================================ { "extends": "../../../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: drive/snippets/drive_v3/file_snippets/upload_basic.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_upload_basic] import fs from 'node:fs'; import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Uploads a file to Google Drive. * @return {Promise} The ID of the uploaded file. */ async function uploadBasic() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // The request body for the file to be uploaded. const requestBody = { name: 'photo.jpg', fields: 'id', }; // The media content to be uploaded. const media = { mimeType: 'image/jpeg', body: fs.createReadStream('files/photo.jpg'), }; // Upload the file. const file = await service.files.create({ requestBody, media, }); // Print the ID of the uploaded file. console.log('File Id:', file.data.id); return file.data.id; } // [END drive_upload_basic] export {uploadBasic}; ================================================ FILE: drive/snippets/drive_v3/file_snippets/upload_to_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_upload_to_folder] import fs from 'node:fs'; import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Uploads a file to the specified folder. * @param {string} folderId The ID of the folder to upload the file to. * @return {Promise} The ID of the uploaded file. */ async function uploadToFolder(folderId) { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // The request body for the file to be uploaded. const requestBody = { name: 'photo.jpg', parents: [folderId], }; // The media content to be uploaded. const media = { mimeType: 'image/jpeg', body: fs.createReadStream('files/photo.jpg'), }; // Upload the file to the specified folder. const file = await service.files.create({ requestBody, media, fields: 'id', }); // Print the ID of the uploaded file. console.log('File Id:', file.data.id); if (!file.data.id) { throw new Error('File ID not found.'); } return file.data.id; } // [END drive_upload_to_folder] export {uploadToFolder}; ================================================ FILE: drive/snippets/drive_v3/file_snippets/upload_with_conversion.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START drive_upload_with_conversion] import fs from 'node:fs'; import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Uploads a file to Google Drive and converts it to a Google Sheet. * @return {Promise} The ID of the uploaded file. */ async function uploadWithConversion() { // Authenticate with Google and get an authorized client. // TODO (developer): Use an appropriate auth mechanism for your app. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client (v3). const service = google.drive({version: 'v3', auth}); // The metadata for the file to be uploaded and converted. const fileMetadata = { name: 'My Report', // The MIME type to convert the file to. mimeType: 'application/vnd.google-apps.spreadsheet', }; // The media content to be uploaded. const media = { mimeType: 'text/csv', body: fs.createReadStream('files/report.csv'), }; // Upload the file with conversion. const file = await service.files.create({ requestBody: fileMetadata, media, fields: 'id', }); // Print the ID of the uploaded file. console.log('File Id:', file.data.id); return file.data.id; } // [END drive_upload_with_conversion] export {uploadWithConversion}; ================================================ FILE: drive/snippets/files/config.json ================================================ { "foo": "bar" } ================================================ FILE: drive/snippets/files/document.txt ================================================ Hello world. ================================================ FILE: drive/snippets/files/report.csv ================================================ "Name", "Phone Number" "Bob", "123-4567" "Mary", "234-5678" ================================================ FILE: drive/snippets/test/helpers.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import fs from 'node:fs'; import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Helper functions for Google Drive */ class Helpers { /** * Creates the Google API Service */ constructor() { const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); this.service = google.drive({version: 'v3', auth}); this.filesToDelete = []; } /** * Resets the test suite. */ reset() { this.filesToDelete = []; } /** * Adds the Drive file ID for deletion on cleanup. * @param {string} id The Drive file ID. */ deleteFileOnCleanup(id) { this.filesToDelete.push(id); } /** * Cleans up the test suite. * @return {Promise} A promise to return the Google API service. */ cleanup() { return Promise.all( this.filesToDelete.map((fileId) => this.service.files.delete({fileId})), ); } /** * Creates a test Drive file. * @param {string} fileMetadata The Drive file's metadata * @param {Media} media A media object * @return {Promise} A promise to return the Google API service. */ async createFile(fileMetadata, media) { const file = await this.service.files.create({ requestBody: fileMetadata, media, fields: 'id', }); this.deleteFileOnCleanup(file.data.id); return file; } /** * Creates a test Google Docs document. * @return {Promise} A promise to return the Google Drive file. */ createTestDocument() { return this.createFile( { name: 'Test Document', mimeType: 'application/vnd.google-apps.document', }, { mimeType: 'text/plain', body: fs.createReadStream('files/document.txt'), }, ); } /** * Uploads a test image to Google Drive. * @return {Promise} A promise to return the Google Drive file. */ async createTestBlob() { const file = await this.createFile( { name: 'photo.jpg', }, { mimeType: 'image/jpeg', body: fs.createReadStream('files/photo.jpg'), }, ); return file; } } export {Helpers}; ================================================ FILE: drive/snippets/test/test_drive_v2_create_drive.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createDrive} from '../drive_v2/drive_snippets/create_drive.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); // Note, you must enable creating shared drives for your service account. // https://support.google.com/a/answer/7337635?hl=en it('should create a shared drive', async () => { const id = await createDrive(); expect(id).toBeDefined(); await helpers.service.teamdrives.delete({teamDriveId: id}); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_create_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createFolder} from '../drive_v2/file snippets/create_folder.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should create a folder', async () => { const id = await createFolder(); expect(id).toBeDefined(); helpers.deleteFileOnCleanup(id); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_create_shortcut.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createShortcut} from '../drive_v2/file snippets/create_shortcut.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should create a shortcut', async () => { const id = await createShortcut(); expect(id).toBeDefined(); helpers.deleteFileOnCleanup(id); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_download_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {downloadFile} from '../drive_v2/file snippets/download_file.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should download a photo', async () => { const file = await helpers.createTestBlob(); const status = await downloadFile(file.data.id); expect(status).toEqual(200); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_export_pdf.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {exportPdf} from '../drive_v2/file snippets/export_pdf.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should export a PDF', async () => { const file = await helpers.createTestDocument(); const result = await exportPdf(file.data.id); expect(result.status).toEqual(200); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_fetch_appdata_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {fetchAppdataFolder} from '../drive_v2/appdata_snippets/fetch_appdata_folder.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should fetch the app data folder', async () => { const id = await fetchAppdataFolder(); expect(id).toBeDefined(); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_fetch_changes.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {fetchChanges} from '../drive_v2/change_snippets/fetch_changes.js'; import {fetchStartPageToken} from '../drive_v2/change_snippets/fetch_start_page_token.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should fetch changes', async () => { const startToken = await fetchStartPageToken(); await helpers.createTestBlob(); const token = await fetchChanges(startToken); expect(token).toBeDefined(); expect(token).not.toEqual(startToken); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_fetch_start_page_token.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {fetchStartPageToken} from '../drive_v2/change_snippets/fetch_start_page_token.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should fetch the start page token', async () => { const token = await fetchStartPageToken(); expect(token).toBeDefined(); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_list_appdata.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {listAppdata} from '../drive_v2/appdata_snippets/list_appdata.js'; import {uploadAppdata} from '../drive_v2/appdata_snippets/upload_appdata.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should list files', async () => { const id = await uploadAppdata('../files/config.json'); helpers.deleteFileOnCleanup(id); const files = await listAppdata(); expect(files.length).toBeGreaterThan(0); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_move_file_to_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createFolder} from '../drive_v2/file snippets/create_folder.js'; import {moveFileToFolder} from '../drive_v2/file snippets/move_file_to_folder.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should move a file', async () => { const folderId = await createFolder(); const file = await helpers.createTestBlob(); helpers.deleteFileOnCleanup(folderId); const movedFileStatus = await moveFileToFolder(file.data.id, folderId); expect(movedFileStatus).toEqual(200); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_recover_drives.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createDrive} from '../drive_v2/drive_snippets/create_drive.js'; import {recoverDrives} from '../drive_v2/drive_snippets/recover_drives.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); // Note, you must enable creating shared drives for your service account. // https://support.google.com/a/answer/7337635?hl=en it('should recover team drives', async () => { await createOrphanedTeamDrive(); const teamDrives = await recoverDrives('soheil@workspacesamples.dev'); expect(teamDrives.length).toBeDefined(); }); /** * Creates a standalone shared drive. * @return {fileId} The id of the new shared drive. */ async function createOrphanedTeamDrive() { const fileId = await createDrive(); const res = await helpers.service.permissions.list({ fileId, supportsTeamDrives: true, }); // console.log(res); res.data.permissions.forEach((permission) => { helpers.service.permissions.delete({ fileId, permissionId: permission.id, supportsTeamDrives: true, }); }); return fileId; } }); ================================================ FILE: drive/snippets/test/test_drive_v2_search_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {searchFile} from '../drive_v2/file snippets/search_file.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should search files', async () => { await helpers.createTestBlob(); const files = await searchFile(); expect(files.length).toBeGreaterThan(0); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_share_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {shareFile} from '../drive_v2/file snippets/share_file.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should share files', async () => { const file = await helpers.createTestBlob(); const ids = await shareFile( file.data.id, 'xyz@workspacesamples.dev', 'workspacesamples.dev', ); expect(ids.length).toEqual(2); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_touch_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {touchFile} from '../drive_v2/file snippets/touch_file.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should update the modified time', async () => { const file = await helpers.createTestBlob(); const now = new Date().toISOString(); const modifiedTime = await touchFile(file.data.id, now); expect(modifiedTime).toEqual(now); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_upload_appdata.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {uploadAppdata} from '../drive_v2/appdata_snippets/upload_appdata.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should upload a file', async () => { const id = await uploadAppdata('../files/config.json'); expect(id).toBeDefined(); helpers.deleteFileOnCleanup(id); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_upload_basic.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {uploadBasic} from '../drive_v2/file snippets/upload_basic.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should upload a photo', async () => { const id = await uploadBasic('../files/photo.jpg'); expect(id).toBeDefined(); helpers.deleteFileOnCleanup(id); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_upload_to_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createFolder} from '../drive_v2/file snippets/create_folder.js'; import {uploadToFolder} from '../drive_v2/file snippets/upload_to_folder.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should upload to a folder', async () => { const folderId = await createFolder(); helpers.deleteFileOnCleanup(folderId); const file = await uploadToFolder(folderId, '../files/photo.jpg'); expect(file).toBeDefined(); helpers.deleteFileOnCleanup(file); }); }); ================================================ FILE: drive/snippets/test/test_drive_v2_upload_with_conversion.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {uploadWithConversion} from '../drive_v2/file snippets/upload_with_conversion.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should upload and convert a document', async () => { const id = await uploadWithConversion('../files/reports.csv'); expect(id).toBeDefined(); helpers.deleteFileOnCleanup(id); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_create_drive.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createDrive} from '../drive_v3/drive_snippets/create_drive.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); // Note, you must enable creating shared drives for your service account. // https://support.google.com/a/answer/7337635?hl=en it('should create a shared drive', async () => { const id = await createDrive(); expect(id).toBeDefined(); await helpers.service.teamdrives.delete({teamDriveId: id}); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_create_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createFolder} from '../drive_v3/file_snippets/create_folder.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should create a folder', async () => { const id = await createFolder(); expect(id).toBeDefined(); helpers.deleteFileOnCleanup(id); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_create_shortcut.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createShortcut} from '../drive_v3/file_snippets/create_shortcut.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should create a shortcut', async () => { const id = await createShortcut(); expect(id).toBeDefined(); helpers.deleteFileOnCleanup(id); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_download_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {downloadFile} from '../drive_v3/file_snippets/download_file.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should download a photo', async () => { const file = await helpers.createTestBlob(); const status = await downloadFile(file.data.id); expect(status).toEqual(200); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_export_pdf.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {exportPdf} from '../drive_v3/file_snippets/export_pdf.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should export a PDF', async () => { const file = await helpers.createTestDocument(); const result = await exportPdf(file.data.id); expect(result.status).toEqual(200); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_fetch_appdata_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {fetchAppdataFolder} from '../drive_v3/appdata_snippets/fetch_appdata_folder.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should fetch the app data folder', async () => { const id = await fetchAppdataFolder(); expect(id).toBeDefined(); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_fetch_changes.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {fetchChanges} from '../drive_v3/change_snippets/fetch_changes.js'; import {fetchStartPageToken} from '../drive_v3/change_snippets/fetch_start_page_token.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should fetch changes', async () => { const startToken = await fetchStartPageToken(); await helpers.createTestBlob(); const token = await fetchChanges(startToken); expect(token).toBeDefined(); expect(token).not.toEqual(startToken); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_fetch_start_page_token.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {fetchStartPageToken} from '../drive_v3/change_snippets/fetch_start_page_token.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should fetch the start page token', async () => { const token = await fetchStartPageToken(); expect(token).toBeDefined(); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_list_appdata.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {listAppdata} from '../drive_v3/appdata_snippets/list_appdata.js'; import {uploadAppdata} from '../drive_v3/appdata_snippets/upload_appdata.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should list files', async () => { const id = await uploadAppdata('../files/config.json'); helpers.deleteFileOnCleanup(id); const files = await listAppdata(); expect(files.length).toBeDefined(); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_move_file_to_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createFolder} from '../drive_v3/file_snippets/create_folder.js'; import {moveFileToFolder} from '../drive_v3/file_snippets/move_file_to_folder.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should move a file', async () => { const folderId = await createFolder(); const file = await helpers.createTestBlob(); helpers.deleteFileOnCleanup(folderId); const movedFileStatus = await moveFileToFolder(file.data.id, folderId); expect(movedFileStatus).toEqual(200); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_recover_drives.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createDrive} from '../drive_v3/drive_snippets/create_drive.js'; import {recoverDrives} from '../drive_v3/drive_snippets/recover_drives.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); // Note, you must enable creating shared drives for your service account. // https://support.google.com/a/answer/7337635?hl=en it('should recover team drives', async () => { await createOrphanedTeamDrive(); const teamDrives = await recoverDrives('soheil@workspacesamples.dev'); expect(teamDrives.length).toBeDefined(); }); /** * Creates a standalone shared drive. * @return {fileId} The id of the new shared drive. */ async function createOrphanedTeamDrive() { const fileId = await createDrive(); const result = await helpers.service.permissions.list({ fileId, supportsTeamDrives: true, }); result.data.permissions.forEach((permission) => { helpers.service.permissions.delete({ fileId, permissionId: permission.id, supportsTeamDrives: true, }); }); return fileId; } }); ================================================ FILE: drive/snippets/test/test_drive_v3_search_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {searchFile} from '../drive_v3/file_snippets/search_file.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should search files', async () => { await helpers.createTestBlob(); const files = await searchFile(); expect(files.length).toBeDefined(); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_share_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {shareFile} from '../drive_v3/file_snippets/share_file.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should share files', async () => { const file = await helpers.createTestBlob(); const ids = await shareFile( file.data.id, 'xyz@workspacesamples.dev', 'workspacesamples.dev', ); expect(ids.length).toEqual(2); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_touch_file.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {touchFile} from '../drive_v3/file_snippets/touch_file.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should update the modified time', async () => { const file = await helpers.createTestBlob(); const now = new Date().toISOString(); const modifiedTime = await touchFile(file.data.id, now); expect(modifiedTime).toEqual(now); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_upload_appdata.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {uploadAppdata} from '../drive_v3/appdata_snippets/upload_appdata.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should upload a file', async () => { const id = await uploadAppdata('../files/config.json'); expect(id).toBeDefined(); helpers.deleteFileOnCleanup(id); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_upload_basic.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {uploadBasic} from '../drive_v3/file_snippets/upload_basic.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should upload a photo', async () => { const id = await uploadBasic('../files/photo.jpg'); expect(id).toBeDefined(); helpers.deleteFileOnCleanup(id); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_upload_to_folder.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createFolder} from '../drive_v3/file_snippets/create_folder.js'; import {uploadToFolder} from '../drive_v3/file_snippets/upload_to_folder.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should upload to a folder', async () => { const folderId = await createFolder(); helpers.deleteFileOnCleanup(folderId); const file = await uploadToFolder(folderId, '../files/photo.jpg'); expect(file).toBeDefined(); helpers.deleteFileOnCleanup(file); }); }); ================================================ FILE: drive/snippets/test/test_drive_v3_upload_with_conversion.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {uploadWithConversion} from '../drive_v3/file_snippets/upload_with_conversion.js'; import {Helpers} from './helpers.js'; describe('Drive snippets', () => { const helpers = new Helpers(); before(() => { helpers.reset(); }); after(() => { return helpers.cleanup(); }); it('should upload and convert a document', async () => { const id = await uploadWithConversion('../files/report.csv'); expect(id).toBeDefined(); helpers.deleteFileOnCleanup(id); }); }); ================================================ FILE: forms/snippets/add_item.js ================================================ // Copyright 2022 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_add_item] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; /** * Creates a new form and adds a video item to it. */ async function addItem() { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: path.join(__dirname, 'credentials.json'), scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth: authClient, }); // The initial form to be created. const newForm = { info: { title: 'Creating a new form for batchUpdate in Node', }, }; // Create the new form. const createResponse = await formsClient.forms.create({ requestBody: newForm, }); if (!createResponse.data.formId) { throw new Error('Form ID not returned.'); } console.log(`New formId was: ${createResponse.data.formId}`); // Request body to add a video item to the form. const update = { requests: [ { createItem: { item: { title: 'Homework video', description: 'Quizzes in Google Forms', videoItem: { video: { youtubeUri: 'https://www.youtube.com/watch?v=Lt5HqPvM-eI', }, }, }, // The location to insert the new item. location: { index: 0, }, }, }, ], }; // Send the batch update request to add the item to the form. const updateResponse = await formsClient.forms.batchUpdate({ formId: createResponse.data.formId, requestBody: update, }); console.log(updateResponse.data); return updateResponse.data; } // [END forms_add_item] export {addItem}; ================================================ FILE: forms/snippets/add_responder.js ================================================ // Copyright 2025 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_add_responder] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {drive} from '@googleapis/drive'; const CREDENTIALS_PATH = path.join(__dirname, 'credentials.json'); const SCOPES = ['https://www.googleapis.com/auth/drive.file']; /** * Adds a responder to a form. * This is done by adding a permission to the form in Google Drive. * * @param {string} formId The ID of the form. * @param {string} email The email of the responder to add. */ async function addResponder(formId, email) { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: CREDENTIALS_PATH, scopes: SCOPES, }); // Create a new Drive API client. const driveService = drive({version: 'v3', auth: authClient}); // The permission body to add a responder. const permissionBody = { role: 'reader', type: 'user', emailAddress: email, view: 'published', }; try { // Create the permission. const result = await driveService.permissions.create({ fileId: formId, requestBody: permissionBody, fields: 'id,emailAddress,role,type,view', sendNotificationEmail: false, // Optional: whether to send a notification email. }); console.log('Responder added:', result.data); } catch (err) { console.error('Error adding responder:', err); } } // [END forms_add_responder] export {addResponder}; ================================================ FILE: forms/snippets/anyone_with_link_responder.js ================================================ // Copyright 2025 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_is_anyone_with_link_responder_js] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {drive} from '@googleapis/drive'; const CREDENTIALS_PATH = path.join(__dirname, 'credentials.json'); const SCOPES = ['https://www.googleapis.com/auth/drive.file']; /** * Checks if anyone with the link is a responder for the form. * This is determined by checking the form's permissions in Google Drive. * * @param {string} formId The ID of the Google Form. */ async function isAnyoneWithLinkResponder(formId) { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: CREDENTIALS_PATH, scopes: SCOPES, }); // Create a new Drive API client. const driveService = drive({version: 'v3', auth: authClient}); let anyoneWithLinkResponder = false; try { // List the permissions for the form. const result = await driveService.permissions.list({ fileId: formId, fields: 'permissions(id,type,role,view)', includePermissionsForView: 'published', }); const permissions = result.data.permissions || []; if (permissions.length === 0) { console.log(`No permissions found for form ID: ${formId}`); } else { // Check if there is a permission that allows anyone with the link to respond. // This is indicated by a permission with type 'anyone', view 'published', and role 'reader'. for (const permission of permissions) { if ( permission.type === 'anyone' && permission.view === 'published' && permission.role === 'reader' ) { anyoneWithLinkResponder = true; break; } } } if (anyoneWithLinkResponder) { console.log( `Form '${formId}' IS configured for 'Anyone with the link' to respond.`, ); } else { console.log( `Form '${formId}' is NOT configured for 'Anyone with the link' to respond.`, ); } } catch (e) { console.error(`Error checking "anyone with link" permission: ${e}`); } } // [END forms_is_anyone_with_link_responder_js] // [START forms_set_anyone_with_link_responder_js] /** * Sets anyone with the link to be a responder for the form. * This is done by adding a permission to the form in Google Drive. * * @param {string} formId The ID of the Google Form. */ async function setAnyoneWithLinkResponder(formId) { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: CREDENTIALS_PATH, scopes: SCOPES, }); // Create a new Drive API client. const driveService = drive({version: 'v3', auth: authClient}); // The permission body to allow anyone with the link to respond. const permissionBody = { type: 'anyone', view: 'published', // Key for making it a responder setting role: 'reader', }; try { // Create the permission for the form. const result = await driveService.permissions.create({ fileId: formId, requestBody: permissionBody, fields: 'id', // Request only needed fields }); console.log( `'Anyone with the link can respond' permission set for form '${formId}'.` + ` Permission ID: ${result.data.id}`, ); } catch (e) { console.error(`Error setting "anyone with link" permission: ${e}`); } } // [END forms_set_anyone_with_link_responder_js] // [START forms_remove_anyone_with_link_responder_js] /** * Removes anyone with the link as a responder for the form. * This is done by removing the corresponding permission from the form in Google Drive. * * @param {string} formId The ID of the Google Form. */ async function removeAnyoneWithLinkResponder(formId) { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: CREDENTIALS_PATH, scopes: SCOPES, }); // Create a new Drive API client. const driveService = drive({version: 'v3', auth: authClient}); let permissionIdToDelete = null; try { // List the permissions for the form to find the one to delete. const result = await driveService.permissions.list({ fileId: formId, fields: 'permissions(id,type,role,view)', includePermissionsForView: 'published', }); const permissions = result.data.permissions || []; // Find the permission that allows anyone with the link to respond. for (const permission of permissions) { if ( permission.type === 'anyone' && permission.role === 'reader' && permission.view === 'published' ) { permissionIdToDelete = permission.id; break; } } if (permissionIdToDelete) { // Delete the permission. await driveService.permissions.delete({ fileId: formId, permissionId: permissionIdToDelete, }); console.log( `Successfully removed permission (ID: ${permissionIdToDelete})` + ` from form '${formId}'.`, ); } else { console.log(`Permission not found for form '${formId}'.`); } } catch (e) { console.error(`Error removing "anyone with link" permission: ${e}`); } } // [END forms_remove_anyone_with_link_responder_js] export { isAnyoneWithLinkResponder, setAnyoneWithLinkResponder, removeAnyoneWithLinkResponder, }; ================================================ FILE: forms/snippets/convert_form.js ================================================ // Copyright 2022 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_convert_form] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; /** * Creates a new form and then converts it into a quiz. */ async function convertForm() { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: path.join(__dirname, 'credentials.json'), scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth: authClient, }); // The initial form to be created. const newForm = { info: { title: 'Creating a new form for batchUpdate in Node', }, }; // Create the new form. const createResponse = await formsClient.forms.create({ requestBody: newForm, }); if (!createResponse.data.formId) { throw new Error('Failed to create form.'); } console.log(`New formId was: ${createResponse.data.formId}`); // Request body to convert the form to a quiz. const updateRequest = { requests: [ { updateSettings: { settings: { quizSettings: { isQuiz: true, }, }, // The updateMask specifies which fields to update. updateMask: 'quizSettings.isQuiz', }, }, ], }; // Send the batch update request to convert the form to a quiz. const result = await formsClient.forms.batchUpdate({ formId: createResponse.data.formId, requestBody: updateRequest, }); console.log(result.data); return result.data; } // [END forms_convert_form] export {convertForm}; ================================================ FILE: forms/snippets/create_form.js ================================================ // Copyright 2022 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_create_form] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; /** * Creates a new form. */ async function createForm() { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: path.join(__dirname, 'credentials.json'), scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth: authClient, }); // The request body to create a new form. const newForm = { info: { title: 'Creating a new form in Node', }, }; // Send the request to create the form. const result = await formsClient.forms.create({ requestBody: newForm, }); console.log(result.data); return result.data; } // [END forms_create_form] export {createForm}; ================================================ FILE: forms/snippets/create_watch.js ================================================ // Copyright 2022 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_create_watch] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; // TODO: Replace with a valid form ID. const formID = ''; /** * Creates a watch on a form to get notifications for new responses. */ async function createWatch() { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: path.join(__dirname, 'credentials.json'), scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth: authClient, }); // The request body to create a watch. const watchRequest = { watch: { target: { topic: { // TODO: Replace with a valid Cloud Pub/Sub topic name. topicName: 'projects/', }, }, // The event type to watch for. 'RESPONSES' is the only supported type. eventType: 'RESPONSES', }, }; // Send the request to create the watch. const result = await formsClient.forms.watches.create({ formId: formID, requestBody: watchRequest, }); console.log(result.data); return result.data; } // [END forms_create_watch] export {createWatch}; ================================================ FILE: forms/snippets/delete_watch.js ================================================ // Copyright 2022 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_delete_watch] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; // TODO: Replace with a valid form ID. const formID = ''; // TODO: Replace with a valid watch ID. const watchID = ''; /** * Deletes a watch from a form. */ async function deleteWatch() { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: path.join(__dirname, 'credentials.json'), scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth: authClient, }); // Send the request to delete the watch. const result = await formsClient.forms.watches.delete({ formId: formID, watchId: watchID, }); console.log(result.data); return result.data; } // [END forms_delete_watch] export {deleteWatch}; ================================================ FILE: forms/snippets/get_all_responses.js ================================================ // Copyright 2022 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_retrieve_all_responses] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; // TODO: Replace with a valid form ID. const formID = ''; /** * Retrieves all responses from a form. */ async function getAllResponses() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ keyfilePath: path.join(__dirname, 'credentials.json'), scopes: 'https://www.googleapis.com/auth/forms.responses.readonly', }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth, }); // Get the list of responses for the form. const result = await formsClient.forms.responses.list({ formId: formID, }); console.log(result.data); return result.data; } // [END forms_retrieve_all_responses] export {getAllResponses}; ================================================ FILE: forms/snippets/get_form.js ================================================ // Copyright 2022 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_retrieve_contents] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; // TODO: Replace with a valid form ID. const formID = ''; /** * Retrieves the content of a form. */ async function getForm() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ keyfilePath: path.join(__dirname, 'credentials.json'), scopes: 'https://www.googleapis.com/auth/forms.body.readonly', }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth, }); // Get the form content. const result = await formsClient.forms.get({formId: formID}); console.log(result.data); return result.data; } // [END forms_retrieve_contents] export {getForm}; ================================================ FILE: forms/snippets/get_responders.js ================================================ // Copyright 2025 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_get_responders] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {drive} from '@googleapis/drive'; const CREDENTIALS_PATH = path.join(__dirname, 'credentials.json'); const SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']; /** * Gets the responders of a form. * This is done by listing the permissions of the form in Google Drive. * * @param {string} formId The ID of the form. */ async function getResponders(formId) { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: CREDENTIALS_PATH, scopes: SCOPES, }); // Create a new Drive API client. const driveService = drive({version: 'v3', auth: authClient}); try { // List the permissions for the form. const result = await driveService.permissions.list({ fileId: formId, includePermissionsForView: 'published', fields: 'permissions(id,emailAddress,type,role,view)', }); const permissions = result.data.permissions || []; if (permissions.length === 0) { console.log(`No permissions found for form ID: ${formId}`); } else { console.log('Responders for this form:'); // A responder is a permission with view='published' and role='reader'. for (const permission of permissions) { if (permission.view === 'published' && permission.role === 'reader') { console.log(`Responder:`, permission); } } } } catch (err) { console.error('Error getting responders :', err); } } // [END forms_get_responders] export {getResponders}; ================================================ FILE: forms/snippets/get_single_response.js ================================================ // Copyright 2022 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_retrieve_single_response] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; // TODO: Replace with a valid form ID. const formID = ''; // TODO: Replace with a valid response ID. const responseID = ''; /** * Retrieves a single response from a form. */ async function getSingleResponse() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ keyfilePath: path.join(__dirname, 'credentials.json'), scopes: 'https://www.googleapis.com/auth/forms.responses.readonly', }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth, }); // Get the specified response from the form. const result = await formsClient.forms.responses.get({ formId: formID, responseId: responseID, }); console.log(result.data); return result.data; } // [END forms_retrieve_single_response] export {getSingleResponse}; ================================================ FILE: forms/snippets/list_watches.js ================================================ // Copyright 2022 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_list_form_watches] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; // TODO: Replace with a valid form ID. const formID = ''; /** * Lists the watches for a given form. */ async function listWatches() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ keyfilePath: path.join(__dirname, 'credentials.json'), scopes: 'https://www.googleapis.com/auth/forms.responses.readonly', }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth, }); // Get the list of watches for the form. const result = await formsClient.forms.watches.list({ formId: formID, }); console.log(result.data); return result.data; } // [END forms_list_form_watches] export {listWatches}; ================================================ FILE: forms/snippets/package.json ================================================ { "name": "forms-api-snippets", "version": "1.0.0", "private": true, "description": "Code snippets for the Sheets API", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "@googleapis/drive": "catalog:", "@googleapis/forms": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: forms/snippets/publish_form.js ================================================ // Copyright 2025 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_publish_form] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; const CREDENTIALS_PATH = path.join(__dirname, 'credentials.json'); const SCOPES = 'https://www.googleapis.com/auth/forms.body'; /** * Publishes a Google Form. * * @param {string} formIdToPublish The ID of the form to publish. */ async function publishForm(formIdToPublish) { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: CREDENTIALS_PATH, scopes: SCOPES, }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth: authClient, }); // The request body to publish the form and start accepting responses. const setPublishSettingsRequest = { publishSettings: { publishState: { isPublished: true, isAcceptingResponses: true, }, }, }; try { // Send the request to update the form's publish settings. const result = await formsClient.forms.setPublishSettings({ formId: formIdToPublish, requestBody: setPublishSettingsRequest, }); console.log('Form publish settings updated:', result.data); } catch (err) { console.error('Error setting publish settings:', err); } } // [END forms_publish_form] export {publishForm}; ================================================ FILE: forms/snippets/remove_responders.js ================================================ // Copyright 2025 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_remove_responder] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {drive} from '@googleapis/drive'; const CREDENTIALS_PATH = path.join(__dirname, 'credentials.json'); const SCOPES = ['https://www.googleapis.com/auth/drive.file']; /** * Remove a responder from a form. * This is done by removing the corresponding permission from the form in Google Drive. * * @param {string} formId The ID of the form. * @param {string} email The email of the responder to remove. */ async function removeResponders(formId, email) { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: CREDENTIALS_PATH, scopes: SCOPES, }); // Create a new Drive API client. const driveService = drive({version: 'v3', auth: authClient}); // List the permissions for the form. const result = await driveService.permissions.list({ fileId: formId, includePermissionsForView: 'published', fields: 'permissions(id,emailAddress,type,role,view)', }); const permissions = result.data.permissions || []; // Find the permission that corresponds to the responder to be removed. const responderToRemove = permissions.find( (permission) => permission.view === 'published' && permission.role === 'reader' && permission.emailAddress === email, ); if (responderToRemove?.id) { const permissionId = responderToRemove.id; // Delete the permission. await driveService.permissions.delete({ fileId: formId, permissionId: responderToRemove.id, }); console.log( `Responder with permission ID '${permissionId}' removed successfully.`, ); } else { console.log('Responder not found for the specified form'); } } // [END forms_remove_responder] export {removeResponders}; ================================================ FILE: forms/snippets/renew_watch.js ================================================ // Copyright 2022 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_renew_watch] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; // TODO: Replace with a valid form ID. const formID = ''; // TODO: Replace with a valid watch ID. const watchID = ''; /** * Renews a watch on a form. */ async function renewWatch() { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: path.join(__dirname, 'credentials.json'), scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth: authClient, }); // Send the request to renew the watch. const result = await formsClient.forms.watches.renew({ formId: formID, watchId: watchID, }); console.log(result.data); return result.data; } // [END forms_renew_watch] export {renewWatch}; ================================================ FILE: forms/snippets/stop_accepting_responses.js ================================================ // Copyright 2025 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_stop_accepting_responses] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; const CREDENTIALS_PATH = path.join(__dirname, 'credentials.json'); const SCOPES = 'https://www.googleapis.com/auth/forms.body'; /** * Stops a form from accepting new responses. * * @param {string} formId The ID of the form. */ async function stopAcceptingResponses(formId) { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: CREDENTIALS_PATH, scopes: SCOPES, }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth: authClient, }); // The request body to stop accepting responses. const setPublishSettingsRequest = { publishSettings: { publishState: { isPublished: true, // Keep the form published. isAcceptingResponses: false, // Stop accepting new responses. }, }, }; try { // Send the request to update the form's settings. const res = await formsClient.forms.setPublishSettings({ formId, requestBody: setPublishSettingsRequest, }); console.log('Form is no longer accepting responses.', res.data); } catch (err) { console.error('Error setting publish settings:', err); } } // [END forms_stop_accepting_responses] export {stopAcceptingResponses}; ================================================ FILE: forms/snippets/supports_publishing.js ================================================ // Copyright 2025 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_supports_publishing] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; const CREDENTIALS_PATH = path.join(__dirname, 'credentials.json'); const SCOPES = 'https://www.googleapis.com/auth/forms.body'; /** * Checks if a form supports the `publishSettings` field, which indicates it is not a legacy form. * * @param {string} formIdToCheck The ID of the form to check. */ async function supportsPublishing(formIdToCheck) { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: CREDENTIALS_PATH, scopes: SCOPES, }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth: authClient, }); try { // Get the form metadata. const result = await formsClient.forms.get({ formId: formIdToCheck, }); const formTitle = result.data.info?.title; // If the 'publishSettings' field exists (even if empty), the form supports the new // publishing model and is not a legacy form. if (result.data && result.data.publishSettings !== undefined) { console.log( `Form '${formIdToCheck}' (Title: ${ formTitle }) is NOT a legacy form (supports publishSettings).`, ); } else { console.log( `Form '${formIdToCheck}' (Title: ${ formTitle }) IS a legacy form (does not have publishSettings field).`, ); } } catch (err) { console.error(`Error getting form metadata for '${formIdToCheck}':`, err); } } // [END forms_supports_publishing] export {supportsPublishing}; ================================================ FILE: forms/snippets/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: forms/snippets/unpublish_form.js ================================================ // Copyright 2025 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_unpublish_form] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; const CREDENTIALS_PATH = path.join(__dirname, 'credentials.json'); const SCOPES = 'https://www.googleapis.com/auth/forms.body'; /** * Unpublishes a Google Form. * * @param {string} formIdToUnpublish The ID of the form to unpublish. */ async function unpublishForm(formIdToUnpublish) { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: CREDENTIALS_PATH, scopes: SCOPES, }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth: authClient, }); // The request body to unpublish the form. const setPublishSettingsRequest = { publishSettings: { publishState: { isPublished: false, }, }, }; try { // Send the request to unpublish the form. const res = await formsClient.forms.setPublishSettings({ formId: formIdToUnpublish, requestBody: setPublishSettingsRequest, }); console.log('Form un-published.', res.data); } catch (err) { console.error('Error setting publish settings:', err); } } // [END forms_unpublish_form] export {unpublishForm}; ================================================ FILE: forms/snippets/update_form.js ================================================ // Copyright 2022 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [START forms_update_form] import path from 'node:path'; import {authenticate} from '@google-cloud/local-auth'; import {forms} from '@googleapis/forms'; /** * Creates a new form and then updates it to add a description. */ async function updateForm() { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ keyfilePath: path.join(__dirname, 'credentials.json'), scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Forms API client. const formsClient = forms({ version: 'v1', auth: authClient, }); // The initial form to be created. const newForm = { info: { title: 'Creating a new form for batchUpdate in Node', }, }; // Create the new form. const createResponse = await formsClient.forms.create({ requestBody: newForm, }); if (!createResponse.data.formId) throw new Error('Form ID not returned.'); console.log(`New formId was: ${createResponse.data.formId}`); // Request body to add a description to the form. const update = { requests: [ { updateFormInfo: { info: { description: "Please complete this quiz based on this week's readings for class.", }, // The updateMask specifies which fields to update. updateMask: 'description', }, }, ], }; // Send the batch update request to update the form. const result = await formsClient.forms.batchUpdate({ formId: createResponse.data.formId, requestBody: update, }); console.log(result.data); return result.data; } // [END forms_update_form] export {updateForm}; ================================================ FILE: gmail/quickstart/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START gmail_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; // The scope for reading Gmail labels. const SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Lists the labels in the user's account. */ async function listLabels() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Gmail API client. const gmail = google.gmail({version: 'v1', auth}); // Get the list of labels. const result = await gmail.users.labels.list({ userId: 'me', }); const labels = result.data.labels; if (!labels || labels.length === 0) { console.log('No labels found.'); return; } console.log('Labels:'); // Print the name of each label. labels.forEach((label) => { console.log(`- ${label.name}`); }); } await listLabels(); // [END gmail_quickstart] ================================================ FILE: gmail/quickstart/package.json ================================================ { "name": "gmail-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Gmail API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: gmail/quickstart/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: meet/README.md ================================================ Additional samples can be found at https://github.com/googleapis/google-cloud-node/tree/main/packages/google-apps-meet ================================================ FILE: meet/quickstart/index.js ================================================ /** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START meet_quickstart] import path from 'node:path'; import process from 'node:process'; import {SpacesServiceClient} from '@google-apps/meet'; import {authenticate} from '@google-cloud/local-auth'; // The scope for creating a new meeting space. const SCOPES = ['https://www.googleapis.com/auth/meetings.space.created']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Creates a new meeting space. */ async function createSpace() { // Authenticate with Google and get an authorized client. const authClient = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Meet API client. const meetClient = new SpacesServiceClient({ authClient, }); // Construct the request to create a new space. The request body is empty. const request = {}; // Run the request to create the space. const response = await meetClient.createSpace(request); // Print the URL of the new meeting. console.log(`Meet URL: ${response[0].meetingUri}`); } await createSpace(); // [END meet_quickstart] ================================================ FILE: meet/quickstart/package.json ================================================ { "name": "google-meet-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google Meet API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-apps/meet": "catalog:", "@google-cloud/local-auth": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: meet/quickstart/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json" } ================================================ FILE: package.json ================================================ { "type": "module", "name": "@googleworkspace/samples", "version": "1.0.0", "description": "Node.js samples for [Google Workspace docs](https://developers.google.com/workspace/).", "license": "MIT", "author": "Grant Timmerman", "keywords": [ "Google Workspace", "Apps Script", "Calendar", "Drive", "Sheets", "Slides", "API" ], "devDependencies": { "@biomejs/biome": "^2.2.4", "@types/jest": "catalog:", "@types/mocha": "catalog:", "@types/node": "catalog:", "turbo": "catalog:" }, "scripts": { "lint": "biome check .", "lint:fix": "biome check --write", "test": "turbo run test", "check": "turbo run check" }, "packageManager": "pnpm@10.15.1", "engines": { "node": ">=20" }, "pnpm": { "overrides": { "googleapis-common": "catalog:", "google-auth-library": "catalog:" } } } ================================================ FILE: people/quickstart/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START people_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; // The scope for reading contacts. const SCOPES = ['https://www.googleapis.com/auth/contacts.readonly']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Prints the display names of the first 10 connections. */ async function listConnectionNames() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new People API client. const service = google.people({version: 'v1', auth}); // Get the list of connections. const result = await service.people.connections.list({ resourceName: 'people/me', pageSize: 10, personFields: 'names,emailAddresses', }); const connections = result.data.connections; if (!connections || connections.length === 0) { console.log('No connections found.'); return; } console.log('Connections:'); // Print the display name of each connection. connections.forEach((person) => { if (person.names && person.names.length > 0) { console.log(person.names[0].displayName); } else { console.log('No display name found for connection.'); } }); } await listConnectionNames(); // [END people_quickstart] ================================================ FILE: people/quickstart/package.json ================================================ { "name": "google-people-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google People API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: people/quickstart/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: pnpm-workspace.yaml ================================================ packages: - '**/*' catalog: '@google-apps/chat': ^0.19.0 '@google-apps/meet': ^0.7.0 '@google-cloud/local-auth': 3.0.1 '@googleapis/drive': ^15.0.0 '@googleapis/forms': ^4.0.1 '@grpc/grpc-js': ^1.13.4 '@types/jest': ^30.0.0 '@types/mocha': ^10.0.10 '@types/node': ^24.4.0 '@types/uuid': ^10.0.0 eslint: ^9.35.0 eslint-config-google: ^0.14.0 expect: ^30.1.2 google-auth-library: 10.3.0 googleapis: 159.0.0 googleapis-common: 8.0.0 mocha: ^11.7.2 open: ^10.2.0 server-destroy: ^1.0.1 turbo: ^2.5.6 typescript: ^5.9.2 uuid: ^8.3.2 ================================================ FILE: sheets/quickstart/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START sheets_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; // The scope for reading spreadsheets. const SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Prints the names and majors of students in a sample spreadsheet: * @see https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit */ async function listMajors() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Sheets API client. const sheets = google.sheets({version: 'v4', auth}); // Get the values from the spreadsheet. const result = await sheets.spreadsheets.values.get({ spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms', range: 'Class Data!A2:E', }); const rows = result.data.values; if (!rows || rows.length === 0) { console.log('No data found.'); return; } console.log('Name, Major:'); // Print the name and major of each student. rows.forEach((row) => { // Print columns A and E, which correspond to indices 0 and 4. console.log(`${row[0]}, ${row[4]}`); }); } await listMajors(); // [END sheets_quickstart] ================================================ FILE: sheets/quickstart/package.json ================================================ { "name": "google-sheets-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google Sheets API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: sheets/quickstart/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: sheets/snippets/package.json ================================================ { "name": "sheets-api-snippets", "version": "1.0.0", "private": true, "description": "Code snippets for the Sheets API", "license": "Apache-2.0", "type": "module", "scripts": { "test": "mocha --timeout 60000" }, "dependencies": { "googleapis": "catalog:" }, "devDependencies": { "expect": "catalog:", "google-auth-library": "catalog:", "mocha": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: sheets/snippets/sheets_append_values.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START sheets_append_values] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Appends values to a spreadsheet. * @param {string} spreadsheetId The ID of the spreadsheet to update. * @param {string} range The range of cells to append to. * @param {string} valueInputOption How the input data should be interpreted. * @param {(string[])[]} _values A 2D array of values to append. * @return {Promise} The response from the append request. */ async function appendValues(spreadsheetId, range, valueInputOption, _values) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/spreadsheets', }); // Create a new Sheets API client. const service = google.sheets({version: 'v4', auth}); // The values to append to the spreadsheet. let values = [ [ // Cell values ... ], // Additional rows ... ]; // [START_EXCLUDE silent] values = _values; // [END_EXCLUDE] // Create the request body. const resource = { values, }; // Append the values to the spreadsheet. const result = await service.spreadsheets.values.append({ spreadsheetId, range, valueInputOption, resource, }); // Log the number of appended cells. console.log(`${result.data.updates.updatedCells} cells appended.`); return result; } // [END sheets_append_values] export {appendValues}; ================================================ FILE: sheets/snippets/sheets_batch_get_values.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START sheets_batch_get_values] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Batch gets cell values from a spreadsheet. * @param {string} spreadsheetId The ID of the spreadsheet. * @param {string} _ranges The ranges of cells to retrieve. * @return {obj} The spreadsheet information. */ async function batchGetValues(spreadsheetId, _ranges) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/spreadsheets', }); // Create a new Sheets API client. const service = google.sheets({version: 'v4', auth}); // The ranges to retrieve from the spreadsheet. let ranges = [ // e.g., 'Sheet1!A1:C5', // 'Sheet2!A1:B3' ]; // [START_EXCLUDE silent] ranges = _ranges; // [END_EXCLUDE silent] // Get the values from the specified ranges. const result = await service.spreadsheets.values.batchGet({ spreadsheetId, ranges, }); console.log(`${result.data.valueRanges.length} ranges retrieved.`); return result; } // [END sheets_batch_get_values] export {batchGetValues}; ================================================ FILE: sheets/snippets/sheets_batch_update.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START sheets_batch_update] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Performs a batch update on a spreadsheet. * Updates the spreadsheet title and finds and replaces a string. * @param {string} spreadsheetId The ID of the spreadsheet to update. * @param {string} title The new title for the spreadsheet. * @param {string} find The string to find. * @param {string} replacement The string to replace the found string with. * @return {Promise} The response from the batch update. */ async function batchUpdate(spreadsheetId, title, find, replacement) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/spreadsheets', }); // Create a new Sheets API client. const service = google.sheets({version: 'v4', auth}); // Create a list of requests to be executed in the batch update. const requests = []; // Request to change the spreadsheet's title. requests.push({ updateSpreadsheetProperties: { properties: { title, }, fields: 'title', }, }); // Request to find and replace text. requests.push({ findReplace: { find, replacement, allSheets: true, }, }); // Add more requests here if needed. // Create the batch update request. const batchUpdateRequest = {requests}; // Execute the batch update request. const response = await service.spreadsheets.batchUpdate({ spreadsheetId, requestBody: batchUpdateRequest, }); // Get the response from the find and replace request and log the number of occurrences. const findReplaceResponse = response.data.replies[1].findReplace; console.log(`${findReplaceResponse.occurrencesChanged} replacements made.`); return response; } // [END sheets_batch_update] export {batchUpdate}; ================================================ FILE: sheets/snippets/sheets_batch_update_values.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START sheets_batch_update_values] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Batch updates values in a spreadsheet. * @param {string} spreadsheetId The ID of the spreadsheet to update. * @param {string} range The range of cells to update. * @param {string} valueInputOption How the input data should be interpreted. * @param {(string[])[]} _values A 2D array of values to update. * @return {Promise} The response from the batch update. */ async function batchUpdateValues( spreadsheetId, range, valueInputOption, _values, ) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/spreadsheets', }); // Create a new Sheets API client. const service = google.sheets({version: 'v4', auth}); // The values to update in the spreadsheet. let values = [ [ // Cell values ... ], // Additional rows ... ]; // [START_EXCLUDE silent] values = _values; // [END_EXCLUDE] // The data to be updated. const data = [ { range, values, }, ]; // Additional ranges to update can be added here. // Create the batch update request. const resource = { data, valueInputOption, }; // Execute the batch update request. const result = await service.spreadsheets.values.batchUpdate({ spreadsheetId, resource, }); // Log the number of updated cells. console.log('%d cells updated.', result.data.totalUpdatedCells); return result; } // [END sheets_batch_update_values] export {batchUpdateValues}; ================================================ FILE: sheets/snippets/sheets_conditional_formatting.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START sheets_conditional_formatting] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Applies conditional formatting to a spreadsheet. * @param {string} spreadsheetId The ID of the spreadsheet. * @return {Promise} The response from the batch update. */ async function conditionalFormatting(spreadsheetId) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/spreadsheets', }); // Create a new Sheets API client. const service = google.sheets({version: 'v4', auth}); // The range to apply the conditional formatting to. const myRange = { sheetId: 0, startRowIndex: 1, endRowIndex: 11, startColumnIndex: 0, endColumnIndex: 4, }; // The requests to apply conditional formatting. const requests = [ { addConditionalFormatRule: { rule: { ranges: [myRange], booleanRule: { condition: { type: 'CUSTOM_FORMULA', values: [{userEnteredValue: '=GT($D2,median($D$2:$D$11))'}], }, format: { textFormat: {foregroundColor: {red: 0.8}}, }, }, }, index: 0, }, }, { addConditionalFormatRule: { rule: { ranges: [myRange], booleanRule: { condition: { type: 'CUSTOM_FORMULA', values: [{userEnteredValue: '=LT($D2,median($D$2:$D$11))'}], }, format: { backgroundColor: {red: 1, green: 0.4, blue: 0.4}, }, }, }, index: 0, }, }, ]; // Create the batch update request. const resource = { requests, }; // Execute the batch update request. const response = await service.spreadsheets.batchUpdate({ spreadsheetId, resource, }); console.log(`${response.data.replies.length} cells updated.`); return response; } // [END sheets_conditional_formatting] export {conditionalFormatting}; ================================================ FILE: sheets/snippets/sheets_create.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START sheets_create] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Creates a new Google Spreadsheet. * @param {string} title The title of the new spreadsheet. * @return {string} The ID of the created spreadsheet. */ async function create(title) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/spreadsheets', }); // Create a new Sheets API client. const service = google.sheets({version: 'v4', auth}); // The resource body for creating a new spreadsheet. const resource = { properties: { title, }, }; // Create the new spreadsheet. const spreadsheet = await service.spreadsheets.create({ resource, fields: 'spreadsheetId', }); // Log the ID of the new spreadsheet. console.log(`Spreadsheet ID: ${spreadsheet.data.spreadsheetId}`); return spreadsheet.data.spreadsheetId; } // [END sheets_create] export {create}; ================================================ FILE: sheets/snippets/sheets_get_values.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START sheets_get_values] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Gets cell values from a spreadsheet. * @param {string} spreadsheetId The ID of the spreadsheet. * @param {string} range The range of cells to retrieve. * @return {Promise} The response from the get request. */ async function getValues(spreadsheetId, range) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/spreadsheets', }); // Create a new Sheets API client. const service = google.sheets({version: 'v4', auth}); // Get the values from the specified range. const result = await service.spreadsheets.values.get({ spreadsheetId, range, }); const numRows = result.data.values ? result.data.values.length : 0; console.log(`${numRows} rows retrieved.`); return result; } // [END sheets_get_values] export {getValues}; ================================================ FILE: sheets/snippets/sheets_pivot_table.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START sheets_pivot_tables] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Creates a pivot table in a spreadsheet. * @param {string} spreadsheetId The ID of the spreadsheet. * @return {Promise} The response from the batch update. */ async function pivotTable(spreadsheetId) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/spreadsheets', }); const service = google.sheets({version: 'v4', auth}); // Create two new sheets for the pivot table. // One for the source data and one for the pivot table itself. let requests = [ { addSheet: {}, }, { addSheet: {}, }, ]; let resource = {requests}; let response = await service.spreadsheets.batchUpdate({ spreadsheetId, resource, }); // Get the IDs of the newly created sheets. const sourceSheetId = response.data.replies[0].addSheet.properties.sheetId; const targetSheetId = response.data.replies[1].addSheet.properties.sheetId; // Add a pivot table to the new sheet. requests = [ { updateCells: { rows: { values: [ { pivotTable: { // The source data for the pivot table. source: { sheetId: sourceSheetId, startRowIndex: 0, startColumnIndex: 0, endRowIndex: 20, endColumnIndex: 7, }, // The rows of the pivot table. rows: [ { sourceColumnOffset: 1, showTotals: true, sortOrder: 'ASCENDING', }, ], // The columns of the pivot table. columns: [ { sourceColumnOffset: 4, sortOrder: 'ASCENDING', showTotals: true, }, ], // The values to display in the pivot table. values: [ { summarizeFunction: 'COUNTA', sourceColumnOffset: 4, }, ], valueLayout: 'HORIZONTAL', }, }, ], }, // The location to place the pivot table. start: { sheetId: targetSheetId, rowIndex: 0, columnIndex: 0, }, fields: 'pivotTable', }, }, ]; resource = { requests, }; // Send the batch update request to create the pivot table. response = service.spreadsheets.batchUpdate({ spreadsheetId, resource, }); return response; } // [END sheets_pivot_tables] export {pivotTable}; ================================================ FILE: sheets/snippets/sheets_update_values.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START sheets_update_values] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Updates values in a spreadsheet. * @param {string} spreadsheetId The ID of the spreadsheet to update. * @param {string} range The range of cells to update. * @param {string} valueInputOption How the input data should be interpreted. * @param {(string[])[]} _values A 2D array of values to update. * @return {Promise} The response from the update request. */ async function updateValues(spreadsheetId, range, valueInputOption, _values) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/spreadsheets', }); // Create a new Sheets API client. const service = google.sheets({version: 'v4', auth}); // The values to update in the spreadsheet. let values = [ [ // Cell values ... ], // Additional rows ... ]; // [START_EXCLUDE silent] values = _values; // [END_EXCLUDE] // Create the request body. const resource = { values, }; // Update the values in the spreadsheet. const result = await service.spreadsheets.values.update({ spreadsheetId, range, valueInputOption, resource, }); // Log the number of updated cells. console.log('%d cells updated.', result.data.updatedCells); return result; } // [END sheets_update_values] export {updateValues}; ================================================ FILE: sheets/snippets/test/helpers.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Helper functions for Google Sheets */ class Helpers { /** * Creates the Google API Service */ constructor() { const auth = new GoogleAuth({ scopes: [ 'https://www.googleapis.com/auth/spreadsheets', 'https://www.googleapis.com/auth/drive', ], }); this.sheetsService = google.sheets({version: 'v4', auth}); this.driveService = google.drive({version: 'v3', auth}); this.filesToDelete = []; } /** * Resets the test suite. */ reset() { this.filesToDelete = []; } /** * Adds the Drive file ID for deletion on cleanup. * @param {string} id The Drive file ID. */ deleteFileOnCleanup(id) { this.filesToDelete.push(id); } /** * Cleans up the test suite. * @return {Promise} returns list of deletion promises */ cleanup() { return Promise.all( this.filesToDelete.map((fileId) => this.driveService.files.delete({fileId}), ), ); } /** * Creates a test Spreadsheet. * @return {Promise} A promise to return the Google API service. */ async createTestSpreadsheet() { const result = await this.sheetsService.spreadsheets.create({ requestBody: { properties: { title: 'Test Spreadsheet', }, }, fields: 'spreadsheetId', }); this.deleteFileOnCleanup(result.data.spreadsheetId); return result.data.spreadsheetId; } /** * Adds a string to a 11x11 grid of Spreadsheet cells. * @param {string} spreadsheetId The spreadsheet ID. * @return {Promise} A promise to return the Google API service. */ async populateValues(spreadsheetId) { await this.sheetsService.spreadsheets.batchUpdate({ spreadsheetId, requestBody: { requests: [ { repeatCell: { range: { sheetId: 0, startRowIndex: 0, endRowIndex: 10, startColumnIndex: 0, endColumnIndex: 10, }, cell: { userEnteredValue: { stringValue: 'Hello', }, }, fields: 'userEnteredValue', }, }, ], }, }); return spreadsheetId; } } export {Helpers}; ================================================ FILE: sheets/snippets/test/test_sheets_append_values.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {appendValues} from '../sheets_append_values.js'; import {Helpers} from './helpers.js'; describe('Spreadsheet append values snippet', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should append values to a spreadsheet', async () => { const spreadsheetId = await helpers.createTestSpreadsheet(); await helpers.populateValues(spreadsheetId); const result = await appendValues(spreadsheetId, 'Sheet1', 'USER_ENTERED', [ ['A', 'B'], ['C', 'D'], ]); expect(result.data.tableRange).toBe('Sheet1!A1:J10'); const updates = result.data.updates; expect(updates.updatedRows).toBe(2); expect(updates.updatedColumns).toBe(2); expect(updates.updatedCells).toBe(4); }); }); ================================================ FILE: sheets/snippets/test/test_sheets_batch_get_values.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {batchGetValues} from '../sheets_batch_get_values.js'; import {Helpers} from './helpers.js'; describe('Spreadsheet batch get values snippet', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should batch get spreadsheet values', async () => { const spreadsheetId = await helpers.createTestSpreadsheet(); await helpers.populateValues(spreadsheetId); const result = await batchGetValues(spreadsheetId, ['A1:A3', 'B1:C1']); const valueRanges = result.data.valueRanges; expect(valueRanges.length).toBe(2); const values = valueRanges[0].values; expect(values.length).toBe(3); }); }); ================================================ FILE: sheets/snippets/test/test_sheets_batch_update.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {batchUpdate} from '../sheets_batch_update.js'; import {Helpers} from './helpers.js'; describe('Spreadsheet batch update snippet', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should batch update a spreadsheet', async () => { const spreadsheetId = await helpers.createTestSpreadsheet(); await helpers.populateValues(spreadsheetId); const result = await batchUpdate( spreadsheetId, 'New Title', 'Hello', 'Goodbye', ); const replies = result.data.replies; expect(replies.length).toBe(2); const findReplaceResponse = replies[1].findReplace; expect(findReplaceResponse.occurrencesChanged).toBe(100); }); }); ================================================ FILE: sheets/snippets/test/test_sheets_batch_update_values.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {batchUpdateValues} from '../sheets_batch_update_values.js'; import {Helpers} from './helpers.js'; describe('Spreadsheet batch update values snippet', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should batch update spreadsheet values', async () => { const spreadsheetId = await helpers.createTestSpreadsheet(); const result = await batchUpdateValues( spreadsheetId, 'A1:B2', 'USER_ENTERED', [ ['A', 'B'], ['C', 'D'], ], ); const responses = result.data.responses; expect(responses.length).toBe(1); expect(result.data.totalUpdatedRows).toBe(2); expect(result.data.totalUpdatedColumns).toBe(2); expect(result.data.totalUpdatedCells).toBe(4); }); }); ================================================ FILE: sheets/snippets/test/test_sheets_conditional_formatting.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {conditionalFormatting} from '../sheets_conditional_formatting.js'; import {Helpers} from './helpers.js'; describe('Spreadsheet conditional formatting snippet', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should conditionally format', async () => { const spreadsheetId = await helpers.createTestSpreadsheet(); await helpers.populateValues(spreadsheetId); const result = await conditionalFormatting(spreadsheetId); expect(result.data.replies.length).toBe(2); }); }); ================================================ FILE: sheets/snippets/test/test_sheets_create.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {create} from '../sheets_create.js'; import {Helpers} from './helpers.js'; describe('Spreadsheet create snippet', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should create a spreadsheet', async () => { const id = await create('Title'); expect(id).toBeDefined(); helpers.deleteFileOnCleanup(id); }); }); ================================================ FILE: sheets/snippets/test/test_sheets_get_values.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {getValues} from '../sheets_get_values.js'; import {Helpers} from './helpers.js'; describe('Spreadsheet get values snippet', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should get spreadsheet values', async () => { const spreadsheetId = await helpers.createTestSpreadsheet(); await helpers.populateValues(spreadsheetId); const result = await getValues(spreadsheetId, 'A1:C2'); const values = result.data.values; expect(values.length).toBe(2); expect(values[0].length).toBe(3); }); }); ================================================ FILE: sheets/snippets/test/test_sheets_pivot_table.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {pivotTable} from '../sheets_pivot_table.js'; import {Helpers} from './helpers.js'; describe('Spreadsheet pivot table snippet', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should create pivot tables', async () => { const spreadsheetId = await helpers.createTestSpreadsheet(); await helpers.populateValues(spreadsheetId); const result = await pivotTable(spreadsheetId); expect(result).toBeDefined(); }); }); ================================================ FILE: sheets/snippets/test/test_sheets_update_values.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {updateValues} from '../sheets_update_values.js'; import {Helpers} from './helpers.js'; describe('Spreadsheet update values snippet', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should update spreadsheet values', async () => { const spreadsheetId = await helpers.createTestSpreadsheet(); const result = await updateValues(spreadsheetId, 'A1:B2', 'USER_ENTERED', [ ['A', 'B'], ['C', 'D'], ]); expect(result.data.updatedRows).toBe(2); expect(result.data.updatedColumns).toBe(2); expect(result.data.updatedCells).toBe(4); }); }); ================================================ FILE: sheets/snippets/tsconfig.json ================================================ { "extends": "../../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: slides/quickstart/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START slides_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; // The scope for reading presentations. const SCOPES = ['https://www.googleapis.com/auth/presentations.readonly']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Prints the number of slides and elements in a sample presentation. * @see https://docs.google.com/presentation/d/1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc/edit */ async function listSlides() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Slides API client. const slidesApi = google.slides({version: 'v1', auth}); // Get the presentation data. const result = await slidesApi.presentations.get({ presentationId: '1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc', }); const slides = result.data.slides; if (!slides || slides.length === 0) { console.log('No slides found.'); return; } // Print the number of slides. console.log('The presentation contains %s slides:', slides.length); // Print the number of elements in each slide. (result.data.slides ?? []).forEach((slide, i) => { console.log( `- Slide #${i + 1} contains ${ slide?.pageElements?.length ?? 0 }} elements.`, ); }); } await listSlides(); // [END slides_quickstart] ================================================ FILE: slides/quickstart/package.json ================================================ { "name": "google-slides-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google Slides API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: slides/quickstart/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: slides/snippets/package.json ================================================ { "name": "slides-api-snippets", "version": "1.0.0", "private": true, "description": "Code snippets for the Sheets API", "license": "Apache-2.0", "type": "module", "scripts": { "test": "mocha --timeout 60000" }, "dependencies": { "googleapis": "catalog:" }, "devDependencies": { "expect": "catalog:", "google-auth-library": "catalog:", "mocha": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: slides/snippets/slides_copy_presentation.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START slides_copy_presentation] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Copies a presentation. * @param {string} presentationId The ID of the presentation to copy. * @param {string} copyTitle The title for the copied presentation. * @return {Promise} The response from the copy request. */ async function copyPresentation(presentationId, copyTitle) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive', }); // Create a new Drive API client. const service = google.drive({version: 'v2', auth}); // The request to copy the presentation. const request = { name: copyTitle, }; // Copy the presentation. const driveResponse = await service.files.copy({ fileId: presentationId, requestBody: request, }); // Log the ID of the copied presentation. const presentationCopyId = driveResponse.data.id; console.log(`Created copied presentation with ID: ${presentationCopyId}`); return driveResponse; } // [END slides_copy_presentation] export {copyPresentation}; ================================================ FILE: slides/snippets/slides_create_bulleted_text.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START slides_create_bulleted_text] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Adds bullet points to text in a shape. * @param {string} presentationId The ID of the presentation. * @param {string} shapeId The ID of the shape to add bullets to. * @return {Promise} The response from the batch update. */ async function createBulletedText(presentationId, shapeId) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/presentations', }); // Create a new Slides API client. const service = google.slides({version: 'v1', auth}); // The request to add bullet points to the text. const requests = [ { createParagraphBullets: { objectId: shapeId, textRange: { type: 'ALL', }, bulletPreset: 'BULLET_ARROW_DIAMOND_DISC', }, }, ]; // Execute the batch update request. const batchUpdateResponse = await service.presentations.batchUpdate({ presentationId, requestBody: { requests, }, }); console.log(`Added bullets to text in shape with ID: ${shapeId}`); return batchUpdateResponse.data; } // [END slides_create_bulleted_text] export {createBulletedText}; ================================================ FILE: slides/snippets/slides_create_image.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START slides_create_image] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Adds an image to a slide in a presentation. * @param {string} presentationId The ID of the presentation. * @param {string} pageId The ID of the page to add the image to. * @return {Promise} The response from the batch update. */ async function createImage(presentationId, pageId) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/presentations', }); // Create a new Slides API client. const service = google.slides({version: 'v1', auth}); // The URL of the image to add. const imageUrl = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png'; // The ID to use for the new image. const imageId = 'MyImage_01'; // The size of the new image in English Metric Units (EMUs). const emu4M = { magnitude: 4000000, unit: 'EMU', }; // The request to create a new image. const requests = [ { createImage: { objectId: imageId, url: imageUrl, elementProperties: { pageObjectId: pageId, size: { height: emu4M, width: emu4M, }, transform: { scaleX: 1, scaleY: 1, translateX: 100000, translateY: 100000, unit: 'EMU', }, }, }, }, ]; // Execute the batch update request to create the image. const response = await service.presentations.batchUpdate({ presentationId, requestBody: {requests}, }); const createImageResponse = response.data.replies; console.log( `Created image with ID: ${createImageResponse[0].createImage.objectId}`, ); return createImageResponse; } // [END slides_create_image] export {createImage}; ================================================ FILE: slides/snippets/slides_create_presentation.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START slides_create_presentation] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Creates a new Google Slides presentation. * @param {string} title The title for the new presentation. * @return {Promise} The created presentation. */ async function createPresentation(title) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/presentations', }); // Create a new Slides API client. const service = google.slides({version: 'v1', auth}); // Create a new presentation with the specified title. const presentation = await service.presentations.create({ title, }); // Log the ID of the new presentation. console.log( `Created presentation with ID: ${presentation.data.presentationId}`, ); return presentation; } // [END slides_create_presentation] export {createPresentation}; ================================================ FILE: slides/snippets/slides_create_sheets_chart.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START slides_create_sheets_chart] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Embeds a Sheets chart into a presentation. * @param {string} presentationId The ID of the presentation. * @param {string} pageId The ID of the page to embed the chart on. * @param {string} spreadsheetId The ID of the spreadsheet containing the chart. * @param {string} sheetChartId The ID of the chart in the spreadsheet. * @return {Promise} The response from the batch update. */ async function createSheetsChart( presentationId, pageId, spreadsheetId, sheetChartId, ) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/presentations', }); // Create a new Slides API client. const service = google.slides({version: 'v1', auth}); // The size of the embedded chart, in English Metric Units (EMUs). const emu4M = { magnitude: 4000000, unit: 'EMU', }; // The ID to use for the embedded chart. const presentationChartId = 'MyEmbeddedChart'; // The request to create a new chart. const requests = [ { createSheetsChart: { objectId: presentationChartId, spreadsheetId, chartId: sheetChartId, // Linking mode allows the chart to be updated if the source sheet changes. linkingMode: 'LINKED', elementProperties: { pageObjectId: pageId, size: { height: emu4M, width: emu4M, }, transform: { scaleX: 1, scaleY: 1, translateX: 100000, translateY: 100000, unit: 'EMU', }, }, }, }, ]; // Execute the batch update request to create the chart. const batchUpdateResponse = await service.presentations.batchUpdate({ presentationId, requestBody: { requests, }, }); console.log(`Added a linked Sheets chart with ID: ${presentationChartId}`); return batchUpdateResponse.data; } // [END slides_create_sheets_chart] export {createSheetsChart}; ================================================ FILE: slides/snippets/slides_create_slide.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START slides_create_slide] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Creates a new slide in a presentation. * @param {string} presentationId The ID of the presentation. * @param {string} pageId The object ID for the new slide. * @return {Promise} The response from the batch update. */ async function createSlide(presentationId, pageId) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/presentations', }); // Create a new Slides API client. const service = google.slides({version: 'v1', auth}); // The request to create a new slide. const requests = [ { createSlide: { objectId: pageId, insertionIndex: '1', slideLayoutReference: { predefinedLayout: 'TITLE_AND_TWO_COLUMNS', }, }, }, ]; // Execute the batch update request to create the slide. const result = await service.presentations.batchUpdate({ presentationId, requestBody: { requests, }, }); console.log( `Created slide with ID: ${result.data.replies[0].createSlide.objectId}`, ); return result; } // [END slides_create_slide] export {createSlide}; ================================================ FILE: slides/snippets/slides_create_textbox_with_text.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START slides_create_textbox_with_text] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Creates a textbox with text on a slide. * @param {string} presentationId The ID of the presentation. * @param {string} pageId The ID of the page to add the textbox to. * @return {Promise} The response from the batch update. */ async function createTextboxWithText(presentationId, pageId) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/presentations', }); // Create a new Slides API client. const service = google.slides({version: 'v1', auth}); // The ID to use for the new textbox. const elementId = 'MyTextBox_01'; // The size of the new textbox, in points. const pt350 = { magnitude: 350, unit: 'PT', }; // The requests to create a textbox and add text to it. const requests = [ { createShape: { objectId: elementId, shapeType: 'TEXT_BOX', elementProperties: { pageObjectId: pageId, size: { height: pt350, width: pt350, }, transform: { scaleX: 1, scaleY: 1, translateX: 350, translateY: 100, unit: 'PT', }, }, }, }, // Insert text into the new textbox. { insertText: { objectId: elementId, insertionIndex: 0, text: 'New Box Text Inserted!', }, }, ]; // Execute the batch update request. const createTextboxWithTextResponse = await service.presentations.batchUpdate( { presentationId, requestBody: {requests}, }, ); const createShapeResponse = createTextboxWithTextResponse.data.replies[0].createShape; console.log(`Created textbox with ID: ${createShapeResponse.objectId}`); return createTextboxWithTextResponse.data; } // [END slides_create_textbox_with_text] export {createTextboxWithText}; ================================================ FILE: slides/snippets/slides_image_merging.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START slides_image_merging] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Replaces shapes in a presentation with images. * @param {string} templatePresentationId The ID of the template presentation. * @param {string} imageUrl The URL of the image to use. * @param {string} customerName The name of the customer for the new presentation title. * @return {Promise} The response from the batch update. */ async function imageMerging(templatePresentationId, imageUrl, customerName) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: [ 'https://www.googleapis.com/auth/presentations', 'https://www.googleapis.com/auth/drive', ], }); // Create new clients for Slides and Drive APIs. const slidesService = google.slides({version: 'v1', auth}); const driveService = google.drive({version: 'v2', auth}); const logoUrl = imageUrl; const customerGraphicUrl = imageUrl; // Duplicate the template presentation. const copyTitle = `${customerName} presentation`; const driveResponse = await driveService.files.copy({ fileId: templatePresentationId, requestBody: { name: copyTitle, }, }); const presentationCopyId = driveResponse.data.id; // Create the image merge requests. const requests = [ { replaceAllShapesWithImage: { imageUrl: logoUrl, replaceMethod: 'CENTER_INSIDE', containsText: { text: '{{company-logo}}', matchCase: true, }, }, }, { replaceAllShapesWithImage: { imageUrl: customerGraphicUrl, replaceMethod: 'CENTER_INSIDE', containsText: { text: '{{customer-graphic}}', matchCase: true, }, }, }, ]; // Execute the requests to replace the shapes with images. const batchUpdateResponse = await slidesService.presentations.batchUpdate({ presentationId: presentationCopyId, requestBody: { requests, }, }); // Count the total number of replacements made. let numReplacements = 0; for (let i = 0; i < batchUpdateResponse.data.replies.length; ++i) { numReplacements += batchUpdateResponse.data.replies[i].replaceAllShapesWithImage .occurrencesChanged; } console.log(`Created merged presentation with ID: ${presentationCopyId}`); console.log(`Replaced ${numReplacements} shapes with images.`); return batchUpdateResponse.data; } // [END slides_image_merging] export {imageMerging}; ================================================ FILE: slides/snippets/slides_refresh_sheets_chart.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START slides_refresh_sheets_chart] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Refreshes an embedded Sheets chart in a presentation. * @param {string} presentationId The ID of the presentation. * @param {string} presentationChartId The ID of the chart to refresh. * @return {Promise} The response from the batch update. */ async function refreshSheetsChart(presentationId, presentationChartId) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/presentations', }); // Create a new Slides API client. const service = google.slides({version: 'v1', auth}); // The request to refresh the chart. const requests = [ { refreshSheetsChart: { objectId: presentationChartId, }, }, ]; // Execute the batch update request to refresh the chart. const batchUpdateResponse = await service.presentations.batchUpdate({ presentationId, requestBody: { requests, }, }); console.log( `Refreshed a linked Sheets chart with ID: ${presentationChartId}`, ); return batchUpdateResponse.data; } // [END slides_refresh_sheets_chart] export {refreshSheetsChart}; ================================================ FILE: slides/snippets/slides_simple_text_replace.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START slides_simple_text_replace] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Replaces all text in a shape with new text. * @param {string} presentationId The ID of the presentation. * @param {string} shapeId The ID of the shape to update. * @param {string} replacementText The text to replace with. * @return {Promise} The response from the batch update. */ async function simpleTextReplace(presentationId, shapeId, replacementText) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/presentations', }); // Create a new Slides API client. const service = google.slides({version: 'v1', auth}); // The requests to delete the existing text and insert the new text. const requests = [ { deleteText: { objectId: shapeId, textRange: { type: 'ALL', }, }, }, { insertText: { objectId: shapeId, insertionIndex: 0, text: replacementText, }, }, ]; // Execute the batch update request. const batchUpdateResponse = await service.presentations.batchUpdate({ presentationId, requestBody: { requests, }, }); console.log(`Replaced text in shape with ID: ${shapeId}`); return batchUpdateResponse.data; } // [END slides_simple_text_replace] export {simpleTextReplace}; ================================================ FILE: slides/snippets/slides_text_merging.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START slides_text_merging] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Merges text from a spreadsheet into a template presentation. * @param {string} templatePresentationId The ID of the template presentation. * @param {string} dataSpreadsheetId The ID of the spreadsheet containing the data. */ async function textMerging(templatePresentationId, dataSpreadsheetId) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: [ 'https://www.googleapis.com/auth/presentations', 'https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/spreadsheets', ], }); // Create new clients for Slides, Sheets, and Drive APIs. const slidesService = google.slides({version: 'v1', auth}); const sheetsService = google.sheets({version: 'v4', auth}); const driveService = google.drive({version: 'v2', auth}); // Use the Sheets API to load data from the spreadsheet. const dataRangeNotation = 'A2:M6'; const sheetsResponse = await sheetsService.spreadsheets.values.get({ spreadsheetId: dataSpreadsheetId, range: dataRangeNotation, }); const values = sheetsResponse.data.values; // For each row of data, create a new presentation by copying the template // and replacing the placeholder text with the data. for (let i = 0; i < values.length; ++i) { const row = values[i]; const customerName = row[2]; // Column 3 const caseDescription = row[5]; // Column 6 const totalPortfolio = row[11]; // Column 12 // Duplicate the template presentation. const title = `${customerName} presentation`; const driveResponse = await driveService.files.copy({ fileId: templatePresentationId, requestBody: { title, }, }); const presentationCopyId = driveResponse.data.id; // Create the text merge requests for this presentation. const requests = [ { replaceAllText: { containsText: { text: '{{customer-name}}', matchCase: true, }, replaceText: customerName, }, }, { replaceAllText: { containsText: { text: '{{case-description}}', matchCase: true, }, replaceText: caseDescription, }, }, { replaceAllText: { containsText: { text: '{{total-portfolio}}', matchCase: true, }, replaceText: totalPortfolio, }, }, ]; // Execute the requests to replace the placeholder text. const batchUpdateResponse = await slidesService.presentations.batchUpdate({ presentationId: presentationCopyId, requestBody: { requests, }, }); const result = batchUpdateResponse.data; // Count the total number of replacements made. let numReplacements = 0; for (let i = 0; i < result.replies.length; ++i) { numReplacements += result.replies[i].replaceAllText.occurrencesChanged; } console.log( `Created presentation for ${customerName} with ID: ${presentationCopyId}`, ); console.log(`Replaced ${numReplacements} text instances.`); } } // [END slides_text_merging] export {textMerging}; ================================================ FILE: slides/snippets/slides_text_style_update.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START slides_text_style_update] import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Updates the text style of a shape in a presentation. * @param {string} presentationId The ID of the presentation. * @param {string} shapeId The ID of the shape to update. * @return {Promise} The response from the batch update. */ async function textStyleUpdate(presentationId, shapeId) { // Authenticate with Google and get an authorized client. const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/presentations', }); // Create a new Slides API client. const service = google.slides({version: 'v1', auth}); // The requests to update the text style. const requests = [ // Bold and italicize the first 5 characters. { updateTextStyle: { objectId: shapeId, textRange: { type: 'FIXED_RANGE', startIndex: 0, endIndex: 5, }, style: { bold: true, italic: true, }, fields: 'bold,italic', }, }, // Set the next 5 characters to 14pt Times New Roman, and blue. { updateTextStyle: { objectId: shapeId, textRange: { type: 'FIXED_RANGE', startIndex: 5, endIndex: 10, }, style: { fontFamily: 'Times New Roman', fontSize: { magnitude: 14, unit: 'PT', }, foregroundColor: { opaqueColor: { rgbColor: { blue: 1.0, green: 0.0, red: 0.0, }, }, }, }, fields: 'foregroundColor,fontFamily,fontSize', }, }, // Hyperlink the next 5 characters. { updateTextStyle: { objectId: shapeId, textRange: { type: 'FIXED_RANGE', startIndex: 10, endIndex: 15, }, style: { link: { url: 'www.example.com', }, }, fields: 'link', }, }, ]; // Execute the batch update request. const batchUpdateResponse = await service.presentations.batchUpdate({ presentationId, requestBody: { requests, }, }); console.log(`Updated the text style for shape with ID: ${shapeId}`); return batchUpdateResponse.data; } // [END slides_text_style_update] export {textStyleUpdate}; ================================================ FILE: slides/snippets/test/helpers.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {GoogleAuth} from 'google-auth-library'; import {google} from 'googleapis'; /** * Helper functions for Google Slides */ class Helpers { /** * Creates the Google API Service */ constructor() { const auth = new GoogleAuth({ scopes: [ 'https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/presentations', 'https://www.googleapis.com/auth/spreadsheets', ], }); this.driveService = google.drive({version: 'v3', auth}); this.slidesService = google.slides({version: 'v1', auth}); this.sheetsService = google.sheets({version: 'v4', auth}); this.filesToDelete = []; } /** * Resets the test suite. */ reset() { this.filesToDelete = []; } /** * Adds the Drive file ID for deletion on cleanup. * @param {string} id The Drive file ID. */ deleteFileOnCleanup(id) { this.filesToDelete.push(id); } /** * Cleans up the test suite. * @return {Promise} returns a list of promises */ cleanup() { return Promise.all( this.filesToDelete.map((fileId) => this.driveService.files.delete({fileId}), ), ); } /** * Creates an empty presentation. * @return {Promise} A promise to return the presentation ID. */ async createTestPresentation() { const result = await this.slidesService.presentations.create({ title: 'Test Preso', }); this.deleteFileOnCleanup(result.data.presentationId); return result.data.presentationId; } /** * Adds slides to a presentation. * @param {string} presentationId The presentation ID * @param {number} num The number of slides to Add * @param {object} predefinedLayout The slides' predefined layout * @return {Promise} A list of slide ids. */ async addSlides(presentationId, num, predefinedLayout) { const requests = []; const slideIds = []; for (let i = 0; i < num; ++i) { slideIds.push(`slide_${i}`); requests.push({ createSlide: { objectId: slideIds[i], slideLayoutReference: { predefinedLayout, }, }, }); } await this.slidesService.presentations.batchUpdate({ presentationId, requestBody: { requests, }, }); return slideIds; } /** * Creates a test textbox * @param {string} presentationId The presentation ID. * @param {string} pageObjectId The element page object ID. * @return {Promise} The textbox's object ID. */ async createTestTextbox(presentationId, pageObjectId) { const boxId = 'MyTextBox_01'; const pt350 = { magnitude: 350, unit: 'PT', }; const requests = [ { createShape: { objectId: boxId, shapeType: 'TEXT_BOX', elementProperties: { pageObjectId, size: { height: pt350, width: pt350, }, transform: { scaleX: 1, scaleY: 1, translateX: 350, translateY: 100, unit: 'PT', }, }, }, }, { insertText: { objectId: boxId, insertionIndex: 0, text: 'New Box Text Inserted', }, }, ]; const result = await this.slidesService.presentations.batchUpdate({ presentationId, requestBody: { requests, }, }); return result.data.replies[0].createShape.objectId; } /** * Creates a test spreadsheet chart * @param {string} presentationId The presentation ID * @param {string} pageId The element page object ID * @param {string} spreadsheetId The Sheet's ID * @param {string} sheetChartId The Sheet's Chart ID * @return {Promise} The chart's object ID */ async createTestSheetsChart( presentationId, pageId, spreadsheetId, sheetChartId, ) { const chartId = 'MyChart_01'; const emu4M = { magnitude: 4000000, unit: 'EMU', }; const requests = [ { createSheetsChart: { objectId: chartId, spreadsheetId, chartId: sheetChartId, linkingMode: 'LINKED', elementProperties: { pageObjectId: pageId, size: { height: emu4M, width: emu4M, }, transform: { scaleX: 1, scaleY: 1, translateX: 100000, translateY: 100000, unit: 'EMU', }, }, }, }, ]; const result = await this.slidesService.presentations.batchUpdate({ presentationId, requestBody: { requests, }, }); return result.data.replies[0].createSheetsChart.objectId; } /** * Creates a test Spreadsheet. * @return {Promise} A promise to return the Google API service. */ async createTestSpreadsheet() { const result = await this.sheetsService.spreadsheets.create({ requestBody: { properties: { title: 'Test Spreadsheet', }, }, fields: 'spreadsheetId', }); this.deleteFileOnCleanup(result.data.spreadsheetId); return result.data.spreadsheetId; } /** * Adds a string to a 11x11 grid of Spreadsheet cells. * @param {string} spreadsheetId The spreadsheet ID. * @return {Promise} A promise to return the Google API service. */ async populateValues(spreadsheetId) { await this.sheetsService.spreadsheets.batchUpdate({ spreadsheetId, requestBody: { requests: [ { repeatCell: { range: { sheetId: 0, startRowIndex: 0, endRowIndex: 15, startColumnIndex: 0, endColumnIndex: 15, }, cell: { userEnteredValue: { stringValue: 'Hello', }, }, fields: 'userEnteredValue', }, }, ], }, }); return spreadsheetId; } } export {Helpers}; ================================================ FILE: slides/snippets/test/test_slides_copy_presentation.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {copyPresentation} from '../slides_copy_presentation.js'; import {Helpers} from './helpers.js'; describe('Presentation snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should copy a presentation', async () => { const presentationId = await helpers.createTestPresentation(); const copyId = await copyPresentation( presentationId, 'My' + ' Duplicate, Presentation', ); expect(copyId).toBeDefined(); helpers.deleteFileOnCleanup(copyId.data.id); }); }); ================================================ FILE: slides/snippets/test/test_slides_create_bulleted_text.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createBulletedText} from '../slides_create_bulleted_text.js'; import {Helpers} from './helpers.js'; describe('Presentation snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should CreateBulletedText', async () => { const presentationId = await helpers.createTestPresentation(); const pageIds = await helpers.addSlides(presentationId, 1, 'BLANK'); const pageId = pageIds[0]; const boxId = await helpers.createTestTextbox(presentationId, pageId); const response = await createBulletedText(presentationId, boxId); expect(1).toEqual(response.replies.length); }); }); ================================================ FILE: slides/snippets/test/test_slides_create_image.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createImage} from '../slides_create_image.js'; import {Helpers} from './helpers.js'; describe('Presentation snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should create an image', async () => { const presentationId = await helpers.createTestPresentation(); const ids = await helpers.addSlides(presentationId, 1, 'BLANK'); const pageId = ids[0]; const response = await createImage(presentationId, pageId); expect(response.length).toBe(1); const imageId = response[0].createImage.objectId; expect(imageId).toBeDefined(); }); }); ================================================ FILE: slides/snippets/test/test_slides_create_presentation.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createPresentation} from '../slides_create_presentation.js'; import {Helpers} from './helpers.js'; describe('Presentation snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should create a presentation', async () => { const presentation = await createPresentation('Title'); expect(presentation).toBeDefined(); helpers.deleteFileOnCleanup(presentation.data.presentationId); }); }); ================================================ FILE: slides/snippets/test/test_slides_create_sheets_chart.js ================================================ // /** // * Copyright 2022 Google LLC // * // * Licensed under the Apache License, Version 2.0 (the "License"); // * you may not use this file except in compliance with the License. // * You may obtain a copy of the License at // * // * https://www.apache.org/licenses/LICENSE-2.0 // * // * Unless required by applicable law or agreed to in writing, software // * distributed under the License is distributed on an "AS IS" BASIS, // * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // * See the License for the specific language governing permissions and // * limitations under the License. // */ import {expect} from 'expect'; import {createSheetsChart} from '../slides_create_sheets_chart.js'; import {Helpers} from './helpers.js'; // Replace with your test spreadsheets id and charts id const CHART_ID = 1107320627; const DATA_SPREADSHEET_ID = '17eqFZl_WK4WVixX8PjvjfLD77DraoFwMDXeiHB3dvuM'; describe('Presentation snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should CreateSheetsChart', async () => { const presentationId = await helpers.createTestPresentation(); const pageIds = await helpers.addSlides(presentationId, 1, 'BLANK'); const pageId = pageIds[0]; const response = await createSheetsChart( presentationId, pageId, DATA_SPREADSHEET_ID, CHART_ID, ); expect(1).toEqual(response.replies.length); const chartId = response.replies[0].createSheetsChart.objectId; expect(chartId).toBeDefined(); }); }); ================================================ FILE: slides/snippets/test/test_slides_create_slide.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createSlide} from '../slides_create_slide.js'; import {Helpers} from './helpers.js'; describe('Presentation snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should create a slide', async () => { const presentationId = await helpers.createTestPresentation(); await helpers.addSlides(presentationId, 3, 'TITLE_AND_TWO_COLUMNS'); const pageId = 'my_page_id'; const response = await createSlide(presentationId, pageId); expect(pageId).toEqual(response.data.replies[0].createSlide.objectId); }); }); ================================================ FILE: slides/snippets/test/test_slides_create_textbox_with_text.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {createTextboxWithText} from '../slides_create_textbox_with_text.js'; import {Helpers} from './helpers.js'; describe('Presentation snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should create a textbox with text', async () => { const presentationId = await helpers.createTestPresentation(); const ids = await helpers.addSlides(presentationId, 1, 'BLANK'); const pageId = ids[0]; const response = await createTextboxWithText(presentationId, pageId); expect(response.replies.length).toEqual(2); const boxId = response.replies[0].createShape.objectId; expect(boxId).toBeDefined(); }); }); ================================================ FILE: slides/snippets/test/test_slides_image_merging.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {imageMerging} from '../slides_image_merging.js'; import {Helpers} from './helpers.js'; const TEMPLATE_PRESENTATION_ID = '1MmTR712m7U_kgeweE57POWwkEyWAV17AVAWjpmltmIg'; const IMAGE_URL = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png'; const CUSTOMER_NAME = 'Fake Customer'; describe('Presentation snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should ImageMerging', async () => { const response = await imageMerging( TEMPLATE_PRESENTATION_ID, IMAGE_URL, CUSTOMER_NAME, ); const presentationId = response.presentationId; expect(presentationId).toBeDefined(); expect(2).toEqual(response.replies.length); let numReplacements = 0; for (let i = 0; i < response.replies.length; ++i) { numReplacements += response.replies[i].replaceAllShapesWithImage.occurrencesChanged; } expect(2).toEqual(numReplacements); }); }); ================================================ FILE: slides/snippets/test/test_slides_refresh_sheets_chart.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {refreshSheetsChart} from '../slides_refresh_sheets_chart.js'; import {Helpers} from './helpers.js'; // Replace with your test spreadsheets id and charts id const CHART_ID = 1107320627; const DATA_SPREADSHEET_ID = '17eqFZl_WK4WVixX8PjvjfLD77DraoFwMDXeiHB3dvuM'; describe('Presentation snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should RefreshSheetsChart', async () => { const presentationId = await helpers.createTestPresentation(); const pageIds = await helpers.addSlides(presentationId, 1, 'BLANK'); const pageId = pageIds[0]; const sheetChartId = await helpers.createTestSheetsChart( presentationId, pageId, DATA_SPREADSHEET_ID, CHART_ID, ); const response = await refreshSheetsChart(presentationId, sheetChartId); expect(1).toEqual(response.replies.length); }); }); ================================================ FILE: slides/snippets/test/test_slides_simple_text_replace.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {simpleTextReplace} from '../slides_simple_text_replace.js'; import {Helpers} from './helpers.js'; describe('Presentation snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should SimpleTextReplace', async () => { const presentationId = await helpers.createTestPresentation(); const pageIds = await helpers.addSlides(presentationId, 1, 'BLANK'); const pageId = pageIds[0]; const boxId = await helpers.createTestTextbox(presentationId, pageId); const response = await simpleTextReplace( presentationId, boxId, 'MY NEW TEXT', ); expect(2).toEqual(response.replies.length); }); }); ================================================ FILE: slides/snippets/test/test_slides_text_merging.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {textMerging} from '../slides_text_merging.js'; import {Helpers} from './helpers.js'; const TEMPLATE_PRESENTATION_ID = '1MmTR712m7U_kgeweE57POWwkEyWAV17AVAWjpmltmIg'; describe('Presentation snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should merge text', async () => { let sheetId = await helpers.createTestSpreadsheet(); sheetId = await helpers.populateValues(sheetId); const responses = await textMerging(TEMPLATE_PRESENTATION_ID, sheetId); // console.log(responses); expect(3).toEqual(responses.replies.length); let numReplacements = 0; for (let i = 0; i < responses.replies.length; ++i) { numReplacements += responses.replies[i].replaceAllText.occurrencesChanged; } expect(4).toEqual(numReplacements); }); }); ================================================ FILE: slides/snippets/test/test_slides_text_style_update.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {expect} from 'expect'; import {textStyleUpdate} from '../slides_text_style_update.js'; import {Helpers} from './helpers.js'; describe('Presentation snippets', () => { const helpers = new Helpers(); after(() => { return helpers.cleanup(); }); it('should TextStyleUpdate', async () => { const presentationId = await helpers.createTestPresentation(); const pageIds = await helpers.addSlides(presentationId, 1, 'BLANK'); const pageId = pageIds[0]; const boxId = await helpers.createTestTextbox(presentationId, pageId); const response = await textStyleUpdate(presentationId, boxId); expect(3).toEqual(response.replies.length); }); }); ================================================ FILE: slides/snippets/tsconfig.json ================================================ { "extends": "../../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: solutions/webhook-chat-app/README.md ================================================ # Google Chat App Webhook Please see related guide on how to [send messages to Google Chat with incoming webhooks](https://developers.google.com/workspace/chat/quickstart/webhooks). ================================================ FILE: solutions/webhook-chat-app/index.js ================================================ /** * Copyright 2022 Google LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START chat_webhook] /** * Sends asynchronous message to Google Chat * @return {Object} response */ async function webhook() { const url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN" const res = await fetch(url, { method: "POST", headers: {"Content-Type": "application/json; charset=UTF-8"}, body: JSON.stringify({ text: "Hello from a Node script!" }) }); return await res.json(); } webhook().then(res => console.log(res)); // [END chat_webhook] ================================================ FILE: solutions/webhook-chat-app/package.json ================================================ { "name": "webhook-chat-app", "version": "1.0.0", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { "node-fetch": "^2.6.0" }, "license": "Apache-2.0" } ================================================ FILE: solutions/webhook-chat-app/thread-reply.js ================================================ /** * Copyright 2023 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START chat_webhook_thread] /** * Sends asynchronous message to Google Chat * @return {Object} response */ async function webhook() { const url = "https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD" const res = await fetch(url, { method: "POST", headers: {"Content-Type": "application/json; charset=UTF-8"}, body: JSON.stringify({ text: "Hello from a Node script!", thread: { threadKey: "THREAD_KEY_VALUE" } }) }); return await res.json(); } webhook().then(res => console.log(res)); // [END chat_webhook_thread] ================================================ FILE: tasks/quickstart/index.js ================================================ /** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START tasks_quickstart] import path from 'node:path'; import process from 'node:process'; import {authenticate} from '@google-cloud/local-auth'; import {google} from 'googleapis'; // The scope for reading tasks. const SCOPES = ['https://www.googleapis.com/auth/tasks.readonly']; // The path to the credentials file. const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json'); /** * Lists the user's first 10 task lists. */ async function listTaskLists() { // Authenticate with Google and get an authorized client. const auth = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); // Create a new Tasks API client. const service = google.tasks({version: 'v1', auth}); // Get the list of task lists. const result = await service.tasklists.list({ maxResults: 10, }); const taskLists = result.data.items; if (taskLists?.length) { console.log('Task lists:'); // Print the title and ID of each task list. taskLists.forEach((taskList) => { console.log(`${taskList.title} (${taskList.id})`); }); } else { console.log('No task lists found.'); } } await listTaskLists(); // [END tasks_quickstart] ================================================ FILE: tasks/quickstart/package.json ================================================ { "name": "google-tasks-nodejs-quickstart", "version": "1.0.0", "private": true, "description": "A simple Node.js command-line application that makes requests to the Google Tasks API.", "license": "Apache-2.0", "type": "module", "scripts": { "check": "tsc --noEmit" }, "dependencies": { "@google-cloud/local-auth": "catalog:", "googleapis": "catalog:" }, "devDependencies": { "google-auth-library": "catalog:", "typescript": "catalog:" }, "engines": { "node": ">=20" } } ================================================ FILE: tasks/quickstart/tsconfig.json ================================================ { "extends": "../../tsconfig.base.json", "include": ["**/*.js"] } ================================================ FILE: tsconfig.base.json ================================================ { "compilerOptions": { "target": "es2022", "module": "node16", "allowJs": true, "checkJs": true, "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "outDir": "./dist" }, "exclude": ["node_modules", "dist"] } ================================================ FILE: turbo.json ================================================ { "$schema": "https://turborepo.org/schema.json", "tasks": { "test": {"inputs": ["**/*.ts", "**/*.js"]}, "check": {"inputs": ["**/*.ts", "**/*.js", "tsconfig.json"]} }, "globalEnv": [ "GOOGLE_APPLICATION_CREDENTIALS", "SERVICE_ACCOUNT_CREDENTIALS", "GOOGLE_CLOUD_PROJECT" ], "globalDependencies": ["pnpm-lock.yaml", "tsconfig.*json"] }