├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE.md ├── linters │ ├── .htmlhintrc │ ├── .yaml-lint.yml │ └── sun_checks.xml ├── sync-repo-settings.yaml └── workflows │ ├── automation.yml │ ├── lint.yml │ └── test.yml ├── .gitignore ├── .rubocop.yml ├── .travis.yml ├── CONTRIBUTING.md ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── SECURITY.md ├── admin_sdk ├── directory │ ├── Gemfile │ ├── Gemfile.lock │ └── quickstart.rb ├── reports │ ├── Gemfile │ ├── Gemfile.lock │ └── quickstart.rb └── reseller │ ├── Gemfile │ ├── Gemfile.lock │ └── quickstart.rb ├── apps_script ├── execute │ └── execute.rb └── quickstart │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ └── quickstart.rb ├── calendar └── quickstart │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ └── quickstart.rb ├── classroom └── quickstart │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ └── quickstart.rb ├── docs └── quickstart │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ └── quickstart.rb ├── drive ├── activity-v2 │ ├── Gemfile │ ├── Gemfile.lock │ └── quickstart.rb ├── activity │ ├── Gemfile │ ├── Gemfile.lock │ └── quickstart.rb ├── quickstart │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ └── quickstart.rb └── snippets │ ├── .gitignore │ ├── Gemfile │ ├── Gemfile.lock │ ├── install.sh │ ├── lib │ ├── drive_snippets.rb │ └── team_drive_snippets.rb │ ├── spec │ ├── drive_snippets_spec.rb │ ├── spec_helper.rb │ └── team_drive_snippets_spec.rb │ └── test.sh ├── gmail └── quickstart │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ └── quickstart.rb ├── people └── quickstart │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ └── quickstart.rb ├── renovate.json ├── sheets ├── quickstart │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ └── quickstart.rb └── snippets │ ├── Gemfile │ ├── install.sh │ ├── lib │ └── spreadsheet_snippets.rb │ ├── spec │ ├── spec_helper.rb │ └── spreadsheet_snippets_spec.rb │ └── test.sh ├── slides ├── quickstart │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ └── quickstart.rb └── snippets │ ├── .gitignore │ ├── Gemfile │ ├── Gemfile.lock │ ├── lib │ └── file_snippets.rb │ ├── run.sh │ ├── setup.sh │ └── spec │ ├── file_snippets_spec.rb │ └── spec_helper.rb └── tasks └── quickstart ├── Gemfile ├── Gemfile.lock └── quickstart.rb /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners 16 | 17 | .github/ @googleworkspace/workspace-devrel-dpe 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Expected Behavior 2 | 3 | 4 | ## Actual Behavior 5 | 6 | 7 | ## Steps to Reproduce the Problem 8 | 9 | 1. 10 | 1. 11 | 1. 12 | 13 | ## Specifications 14 | 15 | - Ruby version (`ruby -v`) 16 | - OS (Mac/Linux/Windows) 17 | -------------------------------------------------------------------------------- /.github/linters/.htmlhintrc: -------------------------------------------------------------------------------- 1 | { 2 | "tagname-lowercase": true, 3 | "attr-lowercase": true, 4 | "attr-value-double-quotes": true, 5 | "attr-value-not-empty": false, 6 | "attr-no-duplication": true, 7 | "doctype-first": false, 8 | "tag-pair": true, 9 | "tag-self-close": false, 10 | "spec-char-escape": false, 11 | "id-unique": true, 12 | "src-not-empty": true, 13 | "title-require": false, 14 | "alt-require": true, 15 | "doctype-html5": true, 16 | "id-class-value": false, 17 | "style-disabled": false, 18 | "inline-style-disabled": false, 19 | "inline-script-disabled": false, 20 | "space-tab-mixed-disabled": "space", 21 | "id-class-ad-disabled": false, 22 | "href-abs-or-rel": false, 23 | "attr-unsafe-chars": true, 24 | "head-script-disabled": false 25 | } 26 | -------------------------------------------------------------------------------- /.github/linters/.yaml-lint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ########################################### 3 | # These are the rules used for # 4 | # linting all the yaml files in the stack # 5 | # NOTE: # 6 | # You can disable line with: # 7 | # # yamllint disable-line # 8 | ########################################### 9 | rules: 10 | braces: 11 | level: warning 12 | min-spaces-inside: 0 13 | max-spaces-inside: 0 14 | min-spaces-inside-empty: 1 15 | max-spaces-inside-empty: 5 16 | brackets: 17 | level: warning 18 | min-spaces-inside: 0 19 | max-spaces-inside: 0 20 | min-spaces-inside-empty: 1 21 | max-spaces-inside-empty: 5 22 | colons: 23 | level: warning 24 | max-spaces-before: 0 25 | max-spaces-after: 1 26 | commas: 27 | level: warning 28 | max-spaces-before: 0 29 | min-spaces-after: 1 30 | max-spaces-after: 1 31 | comments: disable 32 | comments-indentation: disable 33 | document-end: disable 34 | document-start: 35 | level: warning 36 | present: true 37 | empty-lines: 38 | level: warning 39 | max: 2 40 | max-start: 0 41 | max-end: 0 42 | hyphens: 43 | level: warning 44 | max-spaces-after: 1 45 | indentation: 46 | level: warning 47 | spaces: consistent 48 | indent-sequences: true 49 | check-multi-line-strings: false 50 | key-duplicates: enable 51 | line-length: 52 | level: warning 53 | max: 120 54 | allow-non-breakable-words: true 55 | allow-non-breakable-inline-mappings: true 56 | new-line-at-end-of-file: disable 57 | new-lines: 58 | type: unix 59 | trailing-spaces: disable -------------------------------------------------------------------------------- /.github/linters/sun_checks.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 18 | 19 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 65 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 82 | 83 | 84 | 86 | 87 | 88 | 94 | 95 | 96 | 97 | 100 | 101 | 102 | 103 | 104 | 108 | 109 | 110 | 111 | 112 | 114 | 115 | 116 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 135 | 137 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 185 | 186 | 187 | 189 | 191 | 192 | 193 | 194 | 196 | 197 | 198 | 199 | 201 | 202 | 203 | 204 | 206 | 207 | 208 | 209 | 211 | 212 | 213 | 214 | 216 | 217 | 218 | 219 | 221 | 222 | 223 | 224 | 226 | 227 | 228 | 229 | 231 | 232 | 233 | 234 | 236 | 237 | 238 | 239 | 241 | 242 | 243 | 244 | 246 | 247 | 248 | 249 | 251 | 253 | 255 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 287 | 288 | 289 | 292 | 293 | 294 | 295 | 301 | 302 | 303 | 304 | 308 | 309 | 310 | 311 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 326 | 327 | 328 | 329 | 330 | 331 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 347 | 348 | 349 | 350 | 353 | 354 | 355 | 356 | 357 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 371 | 372 | 373 | 374 | -------------------------------------------------------------------------------- /.github/sync-repo-settings.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # .github/sync-repo-settings.yaml 16 | # See https://github.com/googleapis/repo-automation-bots/tree/main/packages/sync-repo-settings for app options. 17 | rebaseMergeAllowed: true 18 | squashMergeAllowed: true 19 | mergeCommitAllowed: false 20 | deleteBranchOnMerge: true 21 | branchProtectionRules: 22 | - pattern: main 23 | isAdminEnforced: false 24 | requiresStrictStatusChecks: false 25 | requiredStatusCheckContexts: 26 | # .github/workflows/test.yml with a job called "test" 27 | - "test" 28 | # .github/workflows/lint.yml with a job called "lint" 29 | - "lint" 30 | # Google bots below 31 | - "cla/google" 32 | - "snippet-bot check" 33 | - "header-check" 34 | - "conventionalcommits.org" 35 | requiredApprovingReviewCount: 1 36 | requiresCodeOwnerReviews: true 37 | permissionRules: 38 | - team: workspace-devrel-dpe 39 | permission: admin 40 | - team: workspace-devrel 41 | permission: push 42 | -------------------------------------------------------------------------------- /.github/workflows/automation.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | --- 15 | name: Automation 16 | on: [ push, pull_request, workflow_dispatch ] 17 | jobs: 18 | dependabot: 19 | runs-on: ubuntu-latest 20 | if: ${{ github.actor == 'dependabot[bot]' && github.event_name == 'pull_request' }} 21 | env: 22 | PR_URL: ${{github.event.pull_request.html_url}} 23 | GITHUB_TOKEN: ${{secrets.GOOGLEWORKSPACE_BOT_TOKEN}} 24 | steps: 25 | - name: approve 26 | run: gh pr review --approve "$PR_URL" 27 | - name: merge 28 | run: gh pr merge --auto --squash --delete-branch "$PR_URL" 29 | default-branch-migration: 30 | # this job helps with migrating the default branch to main 31 | # it pushes main to master if master exists and main is the default branch 32 | # it pushes master to main if master is the default branch 33 | runs-on: ubuntu-latest 34 | if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' }} 35 | steps: 36 | - uses: actions/checkout@v2 37 | with: 38 | fetch-depth: 0 39 | # required otherwise GitHub blocks infinite loops in pushes originating in an action 40 | token: ${{ secrets.GOOGLEWORKSPACE_BOT_TOKEN }} 41 | - name: Set env 42 | run: | 43 | # set DEFAULT BRANCH 44 | echo "DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name')" >> "$GITHUB_ENV"; 45 | 46 | # set HAS_MASTER_BRANCH 47 | if [ -n "$(git ls-remote --heads origin master)" ]; then 48 | echo "HAS_MASTER_BRANCH=true" >> "$GITHUB_ENV" 49 | else 50 | echo "HAS_MASTER_BRANCH=false" >> "$GITHUB_ENV" 51 | fi 52 | env: 53 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 54 | - name: configure git 55 | run: | 56 | git config --global user.name 'googleworkspace-bot' 57 | git config --global user.email 'googleworkspace-bot@google.com' 58 | - if: ${{ env.DEFAULT_BRANCH == 'main' && env.HAS_MASTER_BRANCH == 'true' }} 59 | name: Update master branch from main 60 | run: | 61 | git checkout -B master 62 | git reset --hard origin/main 63 | git push origin master 64 | - if: ${{ env.DEFAULT_BRANCH == 'master'}} 65 | name: Update main branch from master 66 | run: | 67 | git checkout -B main 68 | git reset --hard origin/master 69 | git push origin main 70 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | name: Lint 16 | on: [push, pull_request] 17 | jobs: 18 | lint: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v2 22 | - run: | 23 | echo "No lint checks"; 24 | exit 1; 25 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | name: Test 16 | on: [push, pull_request] 17 | jobs: 18 | test: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v2 22 | - run: | 23 | echo "No tests"; 24 | exit 1; 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # General 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | 6 | # Icon must end with two \r 7 | Icon 8 | 9 | # Thumbnails 10 | ._* 11 | 12 | # Files that might appear in the root of a volume 13 | .DocumentRevisions-V100 14 | .fseventsd 15 | .Spotlight-V100 16 | .TemporaryItems 17 | .Trashes 18 | .VolumeIcon.icns 19 | .com.apple.timemachine.donotpresent 20 | 21 | # Directories potentially created on remote AFP share 22 | .AppleDB 23 | .AppleDesktop 24 | Network Trash Folder 25 | Temporary Items 26 | .apdisk 27 | 28 | # dotenv environment variables file 29 | .env 30 | .DS_Store 31 | 32 | # Secrets 33 | client_secret.json 34 | application_credentials.json 35 | credentials.json 36 | token.yaml 37 | 38 | .ruby-version 39 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Google ruby rules 16 | inherit_gem: 17 | google-style: google-style.yml 18 | 19 | AllCops: 20 | TargetRubyVersion: 2.5 21 | Exclude: 22 | - '**/lib/**/*' 23 | 24 | # Exclude rubocop inheritance 25 | inherit_mode: 26 | merge: 27 | - Exclude 28 | 29 | # G Suite Ruby Samples rules 30 | Metrics/BlockLength: 31 | Max: 200 32 | 33 | Metrics/ModuleLength: 34 | Max: 200 35 | 36 | Style/WordArray: 37 | Enabled: false 38 | 39 | Metrics/MethodLength: 40 | Max: 43 41 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | language: ruby 16 | dist: trusty 17 | sudo: false 18 | cache: bundler 19 | rvm: 20 | - 2.3.7 21 | - 2.4.4 22 | - 2.5.1 23 | before_install: 24 | # https://docs.travis-ci.com/user/languages/ruby/#bundler-20 25 | - gem update --system 26 | - gem install bundler 27 | - gem install rubocop google-style 28 | script: 29 | - rubocop 30 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to become a contributor and submit your own code 2 | 3 | ## Contributor License Agreements 4 | 5 | We'd love to accept your sample apps and patches! Before we can take them, we 6 | have to jump a couple of legal hurdles. 7 | 8 | Please fill out either the individual or corporate Contributor License Agreement 9 | (CLA). 10 | 11 | * If you are an individual writing original source code and you're sure you 12 | own the intellectual property, then you'll need to sign an 13 | [individual CLA](https://developers.google.com/open-source/cla/individual). 14 | * If you work for a company that wants to allow you to contribute your work, 15 | then you'll need to sign a 16 | [corporate CLA](https://developers.google.com/open-source/cla/corporate). 17 | 18 | Follow either of the two links above to access the appropriate CLA and 19 | instructions for how to sign and return it. Once we receive it, we'll be able to 20 | accept your pull requests. 21 | 22 | ## Contributing A Patch 23 | 24 | 1. Submit an issue describing your proposed change to the repo in question. 25 | 1. The repo owner will respond to your issue promptly. 26 | 1. If your proposed change is accepted, and you haven't already done so, sign a Contributor License Agreement (see details above). 27 | 1. Fork the desired repo, develop and test your code changes. 28 | 1. Ensure that your code adheres to the existing style in the sample to which you are contributing. 29 | 1. Ensure that your code has an appropriate set of unit tests which all pass. 30 | 1. Submit a pull request! 31 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Google, Inc 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-style", "~> 0.2", groups: [:development, :test] 18 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | ast (2.4.0) 5 | google-style (0.3.0) 6 | rubocop (~> 0.64.0) 7 | jaro_winkler (1.5.2) 8 | parallel (1.17.0) 9 | parser (2.6.3.0) 10 | ast (~> 2.4.0) 11 | powerpack (0.1.2) 12 | rainbow (3.0.0) 13 | rubocop (0.64.0) 14 | jaro_winkler (~> 1.5.1) 15 | parallel (~> 1.10) 16 | parser (>= 2.5, != 2.5.1.1) 17 | powerpack (~> 0.1) 18 | rainbow (>= 2.2.2, < 4.0) 19 | ruby-progressbar (~> 1.7) 20 | unicode-display_width (~> 1.4.0) 21 | ruby-progressbar (1.10.1) 22 | unicode-display_width (1.4.1) 23 | 24 | PLATFORMS 25 | ruby 26 | 27 | DEPENDENCIES 28 | google-style (~> 0.2) 29 | 30 | BUNDLED WITH 31 | 1.16.2 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Google Workspace Ruby Samples [![Build Status](https://travis-ci.org/googleworkspace/ruby-samples.svg?branch=master)](https://travis-ci.org/googleworkspace/ruby-samples) 2 | 3 | A collection of samples that demonstrate how to call Google Workspace APIs in Ruby. 4 | 5 | ## APIs 6 | 7 | ### Admin SDK 8 | 9 | - [Directory Quickstart](https://developers.google.com/admin-sdk/directory/v1/quickstart/ruby) 10 | - [Reports Quickstart](https://developers.google.com/admin-sdk/reports/v1/quickstart/ruby) 11 | - [Reseller Quickstart](https://developers.google.com/admin-sdk/reseller/v1/quickstart/ruby) 12 | 13 | ### Apps Script 14 | 15 | - [Quickstart](https://developers.google.com/apps-script/api/quickstart/ruby) 16 | 17 | ### Calendar 18 | 19 | - [Quickstart](https://developers.google.com/google-apps/calendar/quickstart/ruby) 20 | 21 | ### Classroom 22 | 23 | - [Quickstart](https://developers.google.com/classroom/quickstart/ruby) 24 | 25 | ### Docs 26 | 27 | - [Quickstart](https://developers.google.com/docs/api/quickstart/ruby) 28 | 29 | ### Drive V3 30 | 31 | - [Quickstart](https://developers.google.com/drive/v3/web/quickstart/ruby) 32 | - [Snippets](https://developers.google.com/drive/v3/web/about-sdk) 33 | 34 | ### Gmail 35 | 36 | - [Quickstart](https://developers.google.com/gmail/api/quickstart/ruby) 37 | 38 | ### Sheets 39 | 40 | - [Quickstart](https://developers.google.com/sheets/api/quickstart/ruby) 41 | - [Snippets](https://developers.google.com/sheets/api/guides/concepts) 42 | 43 | ### Slides 44 | 45 | - [Quickstart](https://developers.google.com/slides/quickstart/ruby) 46 | - [Snippets](https://developers.google.com/slides/how-tos/overview) 47 | 48 | ### Tasks 49 | 50 | - [Quickstart](https://developers.google.com/google-apps/tasks/quickstart/ruby) 51 | 52 | ## Tools 53 | 54 | ### Lint 55 | 56 | ``` 57 | gem install rubocop 58 | rubocop 59 | ``` 60 | 61 | It should not produce any errors, i.e.: 62 | 63 | ```sh 64 | Inspecting 24 files 65 | ........................ 66 | 67 | 24 files inspected, no offenses detected 68 | ``` 69 | 70 | You can fix basic errors with: 71 | 72 | ``` 73 | rubocop --fix 74 | ``` 75 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Report a security issue 2 | 3 | To report a security issue, please use [https://g.co/vulnz](https://g.co/vulnz). We use 4 | [https://g.co/vulnz](https://g.co/vulnz) for our intake, and do coordination and disclosure here on 5 | GitHub (including using GitHub Security Advisory). The Google Security Team will 6 | respond within 5 working days of your report on [https://g.co/vulnz](https://g.co/vulnz). 7 | -------------------------------------------------------------------------------- /admin_sdk/directory/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /admin_sdk/directory/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /admin_sdk/directory/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START admin_sdk_directory_quickstart] 15 | require "google/apis/admin_directory_v1" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Directory API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = Google::Apis::AdminDirectoryV1::AUTH_ADMIN_DIRECTORY_USER_READONLY 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | 54 | # Initialize the API 55 | service = Google::Apis::AdminDirectoryV1::DirectoryService.new 56 | service.client_options.application_name = APPLICATION_NAME 57 | service.authorization = authorize 58 | # List the first 10 users in the domain 59 | response = service.list_users(customer: "my_customer", 60 | max_results: 10, 61 | order_by: "email") 62 | puts "Users:" 63 | puts "No users found" if response.users.empty? 64 | response.users.each { |user| puts "- #{user.primary_email} (#{user.name.full_name})" } 65 | # [END admin_sdk_directory_quickstart] 66 | -------------------------------------------------------------------------------- /admin_sdk/reports/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /admin_sdk/reports/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /admin_sdk/reports/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START admin_sdk_reports_quickstart] 15 | require "google/apis/admin_reports_v1" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Reports API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = Google::Apis::AdminReportsV1::AUTH_ADMIN_REPORTS_AUDIT_READONLY 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | # Initialize the API 54 | service = Google::Apis::AdminReportsV1::ReportsService.new 55 | service.client_options.application_name = APPLICATION_NAME 56 | service.authorization = authorize 57 | 58 | # Print the last 10 login events. 59 | user = "all" 60 | application = "login" 61 | response = service.list_activities user, application, max_results: 10 62 | 63 | puts "Logins:" 64 | puts "No results found" if response.items.empty? 65 | response.items.each do |activity| 66 | puts "- #{activity.id.time}: #{activity.actor.email} (#{activity.events.first.name})" 67 | end 68 | # [END admin_sdk_reports_quickstart] 69 | -------------------------------------------------------------------------------- /admin_sdk/reseller/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /admin_sdk/reseller/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /admin_sdk/reseller/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START admin_sdk_reseller_quickstart] 15 | require "google/apis/reseller_v1" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Reseller API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = Google::Apis::ResellerV1::AUTH_APPS_ORDER 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | # Initialize the API 54 | service = Google::Apis::ResellerV1::ResellerService.new 55 | service.client_options.application_name = APPLICATION_NAME 56 | service.authorization = authorize 57 | 58 | # Print the first 10 subscriptions you manage. 59 | response = service.list_subscriptions max_results: 10 60 | 61 | puts "Subscriptions:" 62 | puts "No subscriptions found" if response.subscriptions.empty? 63 | response.subscriptions.each do |subscription| 64 | puts "- #{subscription.customer_id} (#{subscription.sku_id}, #{subscription.plan.plan_name})" 65 | end 66 | # [END admin_sdk_reseller_quickstart] 67 | -------------------------------------------------------------------------------- /apps_script/execute/execute.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START apps_script_api_execute] 15 | SCRIPT_ID = "ENTER_YOUR_SCRIPT_ID_HERE".freeze 16 | 17 | # Create an execution request object. 18 | request = Google::Apis::ScriptV1::ExecutionRequest.new( 19 | function: "getFoldersUnderRoot" 20 | ) 21 | 22 | begin 23 | # Make the API request. 24 | resp = service.run_script SCRIPT_ID, request 25 | 26 | if resp.error 27 | # The API executed, but the script returned an error. 28 | 29 | # Extract the first (and only) set of error details. The values of this 30 | # object are the script's 'errorMessage' and 'errorType', and an array of 31 | # stack trace elements. 32 | error = resp.error.details[0] 33 | 34 | puts "Script error message: #{error['errorMessage']}" 35 | 36 | if error["scriptStackTraceElements"] 37 | # There may not be a stacktrace if the script didn't start executing. 38 | puts "Script error stacktrace:" 39 | error["scriptStackTraceElements"].each do |trace| 40 | puts "\t#{trace['function']}: #{trace['lineNumber']}" 41 | end 42 | end 43 | else 44 | # The structure of the result will depend upon what the Apps Script function 45 | # returns. Here, the function returns an Apps Script Object with String keys 46 | # and values, and so the result is treated as a Ruby hash (folderSet). 47 | folder_set = resp.response["result"] 48 | if folder_set.empty? 49 | puts "No folders returned!" 50 | else 51 | puts "Folders under your root folder:" 52 | folder_set.each do |id, folder| 53 | puts "\t#{folder} (#{id})" 54 | end 55 | end 56 | end 57 | rescue Google::Apis::ClientError 58 | # The API encountered a problem before the script started executing. 59 | puts "Error calling API!" 60 | end 61 | # [END apps_script_api_execute] 62 | -------------------------------------------------------------------------------- /apps_script/quickstart/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /apps_script/quickstart/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /apps_script/quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Google Apps Script Ruby Quickstart 2 | 3 | Complete the steps described in the [Google Apps Script Ruby Quickstart](https://developers.google.com/apps-script/api/quickstart/ruby), and in about five minutes you'll have a simple Ruby command-line application that makes requests to the Google Apps Script API. 4 | 5 | ## Install 6 | 7 | `bundle install` 8 | 9 | ## Run 10 | 11 | `ruby quickstart.rb` 12 | -------------------------------------------------------------------------------- /apps_script/quickstart/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START apps_script_api_quickstart] 15 | require "google/apis/script_v1" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Google Apps Script API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = "https://www.googleapis.com/auth/script.projects".freeze 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | # Initialize the API 54 | service = Google::Apis::ScriptV1::ScriptService.new 55 | service.client_options.application_name = APPLICATION_NAME 56 | service.authorization = authorize 57 | 58 | # Make the API request. 59 | request = Google::Apis::ScriptV1::CreateProjectRequest.new( 60 | title: "My Script" 61 | ) 62 | resp = service.create_project request 63 | 64 | script_id = resp.script_id 65 | content = Google::Apis::ScriptV1::Content.new( 66 | files: [ 67 | Google::Apis::ScriptV1::File.new( 68 | name: "hello", 69 | type: "SERVER_JS", 70 | source: "function helloWorld() {\n console.log('Hello, world!');\n}" 71 | ), 72 | Google::Apis::ScriptV1::File.new( 73 | name: "appsscript", 74 | type: "JSON", 75 | source: "{\"timeZone\":\"America/New_York\",\"exceptionLogging\": \"CLOUD\"}" 76 | ) 77 | ], 78 | script_id: script_id 79 | ) 80 | service.update_project_content script_id, content 81 | puts "https://script.google.com/d/#{script_id}/edit" 82 | # [END apps_script_api_quickstart] 83 | -------------------------------------------------------------------------------- /calendar/quickstart/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /calendar/quickstart/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /calendar/quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Google Calendar Ruby Quickstart 2 | 3 | Complete the steps described in the [Google Calendar Ruby Quickstart](https://developers.google.com/calendar/quickstart/ruby), and in about five minutes you'll have a simple Ruby command-line application that makes requests to the Google Calendar API. 4 | 5 | ## Install 6 | 7 | `bundle install` 8 | 9 | ## Run 10 | 11 | `ruby quickstart.rb` 12 | -------------------------------------------------------------------------------- /calendar/quickstart/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START calendar_quickstart] 15 | require "google/apis/calendar_v3" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "date" 19 | require "fileutils" 20 | 21 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 22 | APPLICATION_NAME = "Google Calendar API Ruby Quickstart".freeze 23 | CREDENTIALS_PATH = "credentials.json".freeze 24 | # The file token.yaml stores the user's access and refresh tokens, and is 25 | # created automatically when the authorization flow completes for the first 26 | # time. 27 | TOKEN_PATH = "token.yaml".freeze 28 | SCOPE = Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY 29 | 30 | ## 31 | # Ensure valid credentials, either by restoring from the saved credentials 32 | # files or initiating an OAuth2 authorization. If authorization is required, 33 | # the user's default browser will be launched to approve the request. 34 | # 35 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 36 | def authorize 37 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 38 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 39 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 40 | user_id = "default" 41 | credentials = authorizer.get_credentials user_id 42 | if credentials.nil? 43 | url = authorizer.get_authorization_url base_url: OOB_URI 44 | puts "Open the following URL in the browser and enter the " \ 45 | "resulting code after authorization:\n" + url 46 | code = gets 47 | credentials = authorizer.get_and_store_credentials_from_code( 48 | user_id: user_id, code: code, base_url: OOB_URI 49 | ) 50 | end 51 | credentials 52 | end 53 | 54 | # Initialize the API 55 | service = Google::Apis::CalendarV3::CalendarService.new 56 | service.client_options.application_name = APPLICATION_NAME 57 | service.authorization = authorize 58 | 59 | # Fetch the next 10 events for the user 60 | calendar_id = "primary" 61 | response = service.list_events(calendar_id, 62 | max_results: 10, 63 | single_events: true, 64 | order_by: "startTime", 65 | time_min: DateTime.now.rfc3339) 66 | puts "Upcoming events:" 67 | puts "No upcoming events found" if response.items.empty? 68 | response.items.each do |event| 69 | start = event.start.date || event.start.date_time 70 | puts "- #{event.summary} (#{start})" 71 | end 72 | # [END calendar_quickstart] 73 | -------------------------------------------------------------------------------- /classroom/quickstart/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /classroom/quickstart/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /classroom/quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Google Classroom Ruby Quickstart 2 | 3 | Complete the steps described in the [Google Classroom Ruby Quickstart](https://developers.google.com/classroom/quickstart/ruby), and in about five minutes you'll have a simple Ruby command-line application that makes requests to the Google Classroom API. 4 | 5 | ## Install 6 | 7 | `bundle install` 8 | 9 | ## Run 10 | 11 | `ruby quickstart.rb` 12 | -------------------------------------------------------------------------------- /classroom/quickstart/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START classroom_quickstart] 15 | require "google/apis/classroom_v1" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Classroom API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = Google::Apis::ClassroomV1::AUTH_CLASSROOM_COURSES_READONLY 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | # Initialize the API 54 | service = Google::Apis::ClassroomV1::ClassroomService.new 55 | service.client_options.application_name = APPLICATION_NAME 56 | service.authorization = authorize 57 | 58 | # List the first 10 courses the user has access to. 59 | response = service.list_courses page_size: 10 60 | 61 | puts "Courses:" 62 | puts "No courses found" if response.courses.empty? 63 | response.courses.each do |course| 64 | puts "- #{course.name} (#{course.id})" 65 | end 66 | # [END classroom_quickstart] 67 | -------------------------------------------------------------------------------- /docs/quickstart/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /docs/quickstart/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /docs/quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Google Docs API Ruby Quickstart 2 | 3 | Complete the steps described in the [Google Docs API Ruby Quickstart](https://developers.google.com/docs/api/quickstart/ruby), and in about five minutes you'll have a simple Ruby command-line application that makes requests to the Google Docs API. 4 | 5 | ## Install 6 | 7 | `bundle install` 8 | 9 | ## Run 10 | 11 | `ruby quickstart.rb` 12 | 13 | -------------------------------------------------------------------------------- /docs/quickstart/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START docs_quickstart] 15 | require "google/apis/docs_v1" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Google Docs API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = Google::Apis::DocsV1::AUTH_DOCUMENTS_READONLY 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | # Initialize the API 54 | service = Google::Apis::DocsV1::DocsService.new 55 | service.client_options.application_name = APPLICATION_NAME 56 | service.authorization = authorize 57 | 58 | # Prints the title of the sample doc: 59 | # https://docs.google.com/document/d/195j9eDD3ccgjQRttHhJPymLJUCOUjs-jmwTrekvdjFE/edit 60 | document_id = "195j9eDD3ccgjQRttHhJPymLJUCOUjs-jmwTrekvdjFE" 61 | document = service.get_document document_id 62 | puts "The title of the document is: #{document.title}." 63 | # [END docs_quickstart] 64 | -------------------------------------------------------------------------------- /drive/activity-v2/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.29.0" 18 | -------------------------------------------------------------------------------- /drive/activity-v2/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.29.0) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.1) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2019.0331) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.1) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.29.0) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /drive/activity-v2/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START drive_activity_v2_quickstart] 15 | require "google/apis/driveactivity_v2" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Drive Activity API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = Google::Apis::DriveactivityV2::AUTH_DRIVE_ACTIVITY_READONLY 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | # Returns a string representation of the first elements in a list. 54 | def truncated array, limit = 2 55 | contents = array[0...limit].join ", " 56 | more = array.length <= limit ? "" : ", ..." 57 | "[#{contents}#{more}]" 58 | end 59 | 60 | # Returns the name of a set property in an object, or else "unknown". 61 | def get_one_of obj 62 | obj.instance_variables.each do |var| 63 | return var[/^@?(.*)/, 1] 64 | end 65 | "unknown" 66 | end 67 | 68 | # Returns a time associated with an activity. 69 | def get_time_info activity 70 | return activity.timestamp unless activity.timestamp.nil? 71 | return activity.time_range.end_time unless activity.time_range.nil? 72 | 73 | "unknown" 74 | end 75 | 76 | # Returns the type of action. 77 | def get_action_info action_detail 78 | get_one_of action_detail 79 | end 80 | 81 | # Returns user information, or the type of user if not a known user. 82 | def get_user_info user 83 | unless user.known_user.nil? 84 | known_user = user.known_user 85 | is_me = known_user.is_current_user || false 86 | return is_me ? "people/me" : known_user.person_name 87 | end 88 | get_one_of user 89 | end 90 | 91 | # Returns actor information, or the type of actor if not a user. 92 | def get_actor_info actor 93 | return get_user_info actor.user unless actor.user.nil? 94 | 95 | get_one_of actor 96 | end 97 | 98 | # Returns the type of a target and an associated title. 99 | def get_target_info target 100 | if !target.drive_item.nil? 101 | title = target.drive_item.title || "unknown" 102 | return %(driveItem:"#{title}") 103 | elsif !target.drive.nil? 104 | title = target.drive.title || "unknown" 105 | return %(drive:"#{title}") 106 | elsif !target.file_comment.nil? 107 | parent = target.file_comment.parent 108 | title = parent.nil? ? "unknown" : (parent.title || "unknown") 109 | return %(fileComment:"#{title}") 110 | end 111 | "#{get_one_of target}:unknown" 112 | end 113 | 114 | # Initialize the API 115 | service = Google::Apis::DriveactivityV2::DriveActivityService.new 116 | service.client_options.application_name = APPLICATION_NAME 117 | service.authorization = authorize 118 | request = Google::Apis::DriveactivityV2::QueryDriveActivityRequest.new page_size: 10 119 | response = service.query_drive_activity request 120 | puts "Recent activity:" 121 | puts "No activity." if response.activities.empty? 122 | response.activities.each do |activity| 123 | time = get_time_info activity 124 | action = get_action_info activity.primary_action_detail 125 | actors = activity.actors.map { |actor| get_actor_info actor } 126 | targets = activity.targets.map { |target| get_target_info target } 127 | puts "#{time}: #{truncated actors}, #{action}, #{truncated targets}" 128 | end 129 | # [END drive_activity_v2_quickstart] 130 | -------------------------------------------------------------------------------- /drive/activity/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /drive/activity/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /drive/activity/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START drive_activity_quickstart] 15 | require "google/apis/appsactivity_v1" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Drive Activity API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = Google::Apis::AppsactivityV1::AUTH_ACTIVITY 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | # Initialize the API 54 | service = Google::Apis::AppsactivityV1::AppsactivityService.new 55 | service.client_options.application_name = APPLICATION_NAME 56 | service.authorization = authorize 57 | response = service.list_activities(source: "drive.google.com", 58 | drive_ancestor_id: "root", 59 | page_size: 10) 60 | puts "Recent activity:" 61 | puts "No resent activity" if response.activities.empty? 62 | response.activities.each do |activity| 63 | event = activity.combined_event 64 | user = event.user 65 | target = event.target 66 | next if user.nil? || target.nil? 67 | 68 | time = Time.at event.event_time_millis.to_i / 1000 69 | puts "#{time}: #{user.name} #{event.primary_event_type} #{target.name} #{target.mime_type}" 70 | end 71 | # [END drive_activity_quickstart] 72 | -------------------------------------------------------------------------------- /drive/quickstart/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /drive/quickstart/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /drive/quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Google Drive Ruby Quickstart 2 | 3 | Complete the steps described in the [Google Drive Ruby Quickstart](https://developers.google.com/drive/quickstart/ruby), and in about five minutes you'll have a simple Ruby command-line application that makes requests to the Google Drive API. 4 | 5 | ## Install 6 | 7 | `bundle install` 8 | 9 | ## Run 10 | 11 | `ruby quickstart.rb` 12 | -------------------------------------------------------------------------------- /drive/quickstart/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START drive_quickstart] 15 | require "google/apis/drive_v3" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Drive API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | # Initialize the API 54 | drive_service = Google::Apis::DriveV3::DriveService.new 55 | drive_service.client_options.application_name = APPLICATION_NAME 56 | drive_service.authorization = authorize 57 | 58 | # List the 10 most recently modified files. 59 | response = drive_service.list_files(page_size: 10, 60 | fields: "nextPageToken, files(id, name)") 61 | puts "Files:" 62 | puts "No files found" if response.files.empty? 63 | response.files.each do |file| 64 | puts "#{file.name} (#{file.id})" 65 | end 66 | # [END drive_quickstart] 67 | -------------------------------------------------------------------------------- /drive/snippets/.gitignore: -------------------------------------------------------------------------------- 1 | files 2 | -------------------------------------------------------------------------------- /drive/snippets/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "activesupport", ">= 4.2", "< 5.1" 18 | gem "google-api-client", "~> 0.11" 19 | gem "rspec", "~> 3.0" 20 | gem "thor", "~> 0.19" 21 | -------------------------------------------------------------------------------- /drive/snippets/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (5.0.3) 5 | concurrent-ruby (~> 1.0, >= 1.0.2) 6 | i18n (~> 0.7) 7 | minitest (~> 5.1) 8 | tzinfo (~> 1.1) 9 | addressable (2.5.2) 10 | public_suffix (>= 2.0.2, < 4.0) 11 | concurrent-ruby (1.0.5) 12 | declarative (0.0.10) 13 | declarative-option (0.1.0) 14 | diff-lcs (1.3) 15 | faraday (0.13.1) 16 | multipart-post (>= 1.2, < 3) 17 | google-api-client (0.17.1) 18 | addressable (~> 2.5, >= 2.5.1) 19 | googleauth (>= 0.5, < 0.7.0) 20 | httpclient (>= 2.8.1, < 3.0) 21 | mime-types (~> 3.0) 22 | representable (~> 3.0) 23 | retriable (>= 2.0, < 4.0) 24 | googleauth (0.6.2) 25 | faraday (~> 0.12) 26 | jwt (>= 1.4, < 3.0) 27 | logging (~> 2.0) 28 | memoist (~> 0.12) 29 | multi_json (~> 1.11) 30 | os (~> 0.9) 31 | signet (~> 0.7) 32 | httpclient (2.8.3) 33 | i18n (0.8.4) 34 | jwt (1.5.6) 35 | little-plugger (1.1.4) 36 | logging (2.2.2) 37 | little-plugger (~> 1.1) 38 | multi_json (~> 1.10) 39 | memoist (0.16.0) 40 | mime-types (3.1) 41 | mime-types-data (~> 3.2015) 42 | mime-types-data (3.2016.0521) 43 | minitest (5.10.2) 44 | multi_json (1.12.2) 45 | multipart-post (2.0.0) 46 | os (0.9.6) 47 | public_suffix (2.0.5) 48 | representable (3.0.4) 49 | declarative (< 0.1.0) 50 | declarative-option (< 0.2.0) 51 | uber (< 0.2.0) 52 | retriable (3.1.1) 53 | rspec (3.6.0) 54 | rspec-core (~> 3.6.0) 55 | rspec-expectations (~> 3.6.0) 56 | rspec-mocks (~> 3.6.0) 57 | rspec-core (3.6.0) 58 | rspec-support (~> 3.6.0) 59 | rspec-expectations (3.6.0) 60 | diff-lcs (>= 1.2.0, < 2.0) 61 | rspec-support (~> 3.6.0) 62 | rspec-mocks (3.6.0) 63 | diff-lcs (>= 1.2.0, < 2.0) 64 | rspec-support (~> 3.6.0) 65 | rspec-support (3.6.0) 66 | signet (0.8.1) 67 | addressable (~> 2.3) 68 | faraday (~> 0.9) 69 | jwt (>= 1.5, < 3.0) 70 | multi_json (~> 1.10) 71 | thor (0.19.4) 72 | thread_safe (0.3.6) 73 | tzinfo (1.2.3) 74 | thread_safe (~> 0.1) 75 | uber (0.1.0) 76 | 77 | PLATFORMS 78 | ruby 79 | 80 | DEPENDENCIES 81 | activesupport (>= 4.2, < 5.1) 82 | google-api-client (~> 0.11) 83 | rspec (~> 3.0) 84 | thor (~> 0.19) 85 | 86 | BUNDLED WITH 87 | 1.16.1 88 | -------------------------------------------------------------------------------- /drive/snippets/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | rvm install ruby-2.3 17 | rvm use 2.3 18 | rbenv install -s 19 | gem install bundler 20 | bundler install 21 | -------------------------------------------------------------------------------- /drive/snippets/lib/drive_snippets.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | require 'google/apis/drive_v3' 16 | require 'securerandom' 17 | 18 | class DriveSnippets 19 | def initialize(service) 20 | @service = service 21 | end 22 | 23 | def drive_service 24 | @service 25 | end 26 | 27 | def upload_basic 28 | # [START drive_upload_basic] 29 | file_metadata = { 30 | name: 'photo.jpg' 31 | } 32 | file = drive_service.create_file(file_metadata, 33 | fields: 'id', 34 | upload_source: 'files/photo.jpg', 35 | content_type: 'image/jpeg') 36 | puts "File Id: #{file.id}" 37 | # [END drive_upload_basic] 38 | file.id 39 | end 40 | 41 | def upload_revision(id) 42 | # [START drive_upload_revision] 43 | file_metadata = {} 44 | file = drive_service.update_file(id, 45 | file_metadata, 46 | fields: 'id', 47 | upload_source: 'files/photo.jpg', 48 | content_type: 'image/jpeg') 49 | puts "File Id: #{file.id}" 50 | # [END drive_upload_revision] 51 | file.id 52 | end 53 | 54 | def upload_to_folder(real_folder_id) 55 | # [START drive_upload_to_folder] 56 | folder_id = '0BwwA4oUTeiV1TGRPeTVjaWRDY1E' 57 | # [START_EXCLUDE silent] 58 | folder_id = real_folder_id 59 | # [END_EXCLUDE] 60 | file_metadata = { 61 | name: 'photo.jpg', 62 | parents: [folder_id] 63 | } 64 | file = drive_service.create_file(file_metadata, 65 | fields: 'id', 66 | upload_source: 'files/photo.jpg', 67 | content_type: 'image/jpeg') 68 | puts "File Id: #{file.id}" 69 | # [END drive_upload_to_folder] 70 | file.id 71 | end 72 | 73 | def upload_with_conversion 74 | # [START drive_upload_with_conversion] 75 | file_metadata = { 76 | name: 'My Report', 77 | mime_type: 'application/vnd.google-apps.spreadsheet' 78 | } 79 | file = drive_service.create_file(file_metadata, 80 | fields: 'id', 81 | upload_source: 'files/report.csv', 82 | content_type: 'text/csv') 83 | puts "File Id: #{file.id}" 84 | # [END drive_upload_with_conversion] 85 | return file.id 86 | end 87 | 88 | def export_pdf(real_file_id) 89 | # [START drive_export_pdf] 90 | file_id = '1ZdR3L3qP4Bkq8noWLJHSr_iBau0DNT4Kli4SxNc2YEo' 91 | # [START_EXCLUDE silent] 92 | file_id = real_file_id 93 | # [END_EXCLUDE] 94 | content = drive_service.export_file(file_id, 95 | 'application/pdf', 96 | download_dest: StringIO.new) 97 | # [END drive_export_pdf] 98 | return content 99 | end 100 | 101 | def download_file(real_file_id) 102 | # [START drive_download_file] 103 | file_id = '0BwwA4oUTeiV1UVNwOHItT0xfa2M' 104 | # [START_EXCLUDE silent] 105 | file_id = real_file_id 106 | # [END_EXCLUDE] 107 | content = drive_service.get_file(file_id, download_dest: StringIO.new) 108 | # [END drive_download_file] 109 | return content 110 | end 111 | 112 | def create_shortcut 113 | # [START drive_create_shortcut] 114 | file_metadata = { 115 | name: 'Project plan', 116 | mime_type: 'application/vnd.google-apps.drive-sdk' 117 | } 118 | file = drive_service.create_file(file_metadata, fields: 'id') 119 | puts "File Id: #{file.id}" 120 | # [END drive_create_shortcut] 121 | return file.id 122 | end 123 | 124 | def touch_file(real_file_id, real_timestamp) 125 | # [START drive_touch_file] 126 | file_id = '1sTWaJ_j7PkjzaBWtNc3IzovK5hQf21FbOw9yLeeLPNQ'; 127 | file_metadata = { 128 | modified_time: DateTime.now 129 | } 130 | # [START_EXCLUDE silent] 131 | file_id = real_file_id 132 | file_metadata[:modified_time] = real_timestamp 133 | # [END_EXCLUDE] 134 | file = drive_service.update_file(file_id, 135 | file_metadata, 136 | fields: 'id, modifiedTime') 137 | puts "Modified time: #{file.modified_time}" 138 | # [END drive_touch_file] 139 | return file.modified_time 140 | end 141 | 142 | def create_folder 143 | # [START drive_create_folder] 144 | file_metadata = { 145 | name: 'Invoices', 146 | mime_type: 'application/vnd.google-apps.folder' 147 | } 148 | file = drive_service.create_file(file_metadata, fields: 'id') 149 | puts "Folder Id: #{file.id}" 150 | # [END drive_create_folder] 151 | return file.id 152 | end 153 | 154 | def move_file_to_folder(real_file_id, real_folder_id) 155 | # [START drive_move_file_to_folder] 156 | file_id = '1sTWaJ_j7PkjzaBWtNc3IzovK5hQf21FbOw9yLeeLPNQ' 157 | folder_id = '0BwwA4oUTeiV1TGRPeTVjaWRDY1E' 158 | # [START_EXCLUDE silent] 159 | file_id = real_file_id 160 | folder_id = real_folder_id 161 | # [END_EXCLUDE] 162 | # Retrieve the existing parents to remove 163 | file = drive_service.get_file(file_id, 164 | fields: 'parents') 165 | previous_parents = file.parents.join(',') 166 | # Move the file to the new folder 167 | file = drive_service.update_file(file_id, 168 | add_parents: folder_id, 169 | remove_parents: previous_parents, 170 | fields: 'id, parents') 171 | # [END drive_move_file_to_folder] 172 | return file.parents 173 | end 174 | 175 | def search_files 176 | # [START drive_search_files] 177 | files = drive_service.fetch_all(items: :files) do |page_token| 178 | drive_service.list_files(q: "mimeType='image/jpeg'", 179 | spaces: 'drive', 180 | fields: 'nextPageToken, files(id, name)', 181 | page_token: page_token) 182 | end 183 | for file in files 184 | # Process change 185 | puts "Found file: #{file.name} #{file.id}" 186 | end 187 | # [END drive_search_files] 188 | return files.to_a 189 | end 190 | 191 | def share_file(real_file_id, real_user, real_domain) 192 | ids = [] 193 | # [START drive_share_file] 194 | file_id = '1sTWaJ_j7PkjzaBWtNc3IzovK5hQf21FbOw9yLeeLPNQ' 195 | # [START_EXCLUDE silent] 196 | file_id = real_file_id 197 | # [END_EXCLUDE] 198 | callback = lambda do |res, err| 199 | if err 200 | # Handle error... 201 | puts err.body 202 | else 203 | puts "Permission ID: #{res.id}" 204 | # [START_EXCLUDE silent] 205 | ids << res.id 206 | # [END_EXCLUDE] 207 | end 208 | end 209 | drive_service.batch do |service| 210 | user_permission = { 211 | type: 'user', 212 | role: 'writer', 213 | email_address: 'user@example.com' 214 | } 215 | # [START_EXCLUDE silent] 216 | user_permission[:email_address] = real_user 217 | # [END_EXCLUDE] 218 | service.create_permission(file_id, 219 | user_permission, 220 | fields: 'id', 221 | &callback) 222 | domain_permission = { 223 | type: 'domain', 224 | role: 'reader', 225 | domain: 'example.com' 226 | } 227 | # [START_EXCLUDE silent] 228 | domain_permission[:domain] = real_domain 229 | # [END_EXCLUDE] 230 | service.create_permission(file_id, 231 | domain_permission, 232 | fields: 'id', 233 | &callback) 234 | end 235 | # [END drive_share_file] 236 | return ids 237 | end 238 | 239 | def fetch_start_page_token 240 | # [START drive_fetch_start_page_token] 241 | response = drive_service.get_changes_start_page_token 242 | puts "Start token: #{response.start_page_token}" 243 | # [END drive_fetch_start_page_token] 244 | return response.start_page_token 245 | end 246 | 247 | def fetch_changes(saved_start_page_token) 248 | # [START drive_fetch_changes] 249 | # Begin with our last saved start token for this user or the 250 | # current token from get_changes_start_page_token() 251 | page_token = saved_start_page_token; 252 | while page_token do 253 | response = drive_service.list_changes(page_token, 254 | spaces: 'drive') 255 | for change in response.changes 256 | # Process change 257 | puts "Change found for file: #{change.file_id}" 258 | end 259 | if response.new_start_page_token 260 | # Last page, save this token for the next polling interval 261 | saved_start_page_token = response.new_start_page_token 262 | end 263 | page_token = response.next_page_token 264 | end 265 | # [END drive_fetch_changes] 266 | return saved_start_page_token 267 | end 268 | 269 | def upload_app_data 270 | # [START drive_upload_app_data] 271 | file_metadata = { 272 | name: 'config.json', 273 | parents: ['appDataFolder'] 274 | } 275 | file = drive_service.create_file(file_metadata, 276 | fields: 'id', 277 | upload_source: 'files/config.json', 278 | content_type: 'application/json') 279 | puts "File Id: #{file.id}" 280 | # [END drive_upload_app_data] 281 | file.id 282 | end 283 | 284 | def list_app_data 285 | # [START drive_list_app_data] 286 | response = drive_service.list_files(spaces: 'appDataFolder', 287 | fields: 'nextPageToken, files(id, name)', 288 | page_size: 10) 289 | for file in response.files 290 | # Process change 291 | puts "Found file: #{file.name} #{file.id}" 292 | end 293 | # [END drive_list_app_data] 294 | return response.files 295 | end 296 | 297 | def fetch_app_data_folder 298 | # [START drive_fetch_app_data_folder] 299 | file = drive_service.get_file('appDataFolder', fields: 'id') 300 | puts "Folder Id: #{file.id}" 301 | # [END drive_fetch_app_data_folder] 302 | file.id 303 | end 304 | 305 | def create_team_drive 306 | # [START drive_create_team_drive] 307 | team_drive_metadata = { 308 | name: 'Project Resources' 309 | } 310 | request_id = SecureRandom.uuid 311 | team_drive = drive_service.create_teamdrive(request_id, 312 | team_drive_metadata, 313 | fields: 'id') 314 | puts "Team Drive Id: #{team_drive.id}" 315 | # [END drive_create_team_drive] 316 | team_drive.id 317 | end 318 | 319 | def recover_team_drives(real_user) 320 | # [START drive_recover_team_drives] 321 | # Find all Team Drives without an organizer and add one. 322 | # Note: This example does not capture all cases. Team Drives 323 | # that have an empty group as the sole organizer, or an 324 | # organizer outside the organization are not captured. A 325 | # more exhaustive approach would evaluate each Team Drive 326 | # and the associated permissions and groups to ensure an active 327 | # organizer is assigned. 328 | new_organizer_permission = { 329 | type: 'user', 330 | role: 'organizer', 331 | email_address: 'user@example.com' 332 | } 333 | # [START_EXCLUDE silent] 334 | new_organizer_permission[:email_address] = real_user 335 | # [END_EXCLUDE] 336 | 337 | team_drives = drive_service.fetch_all(items: :team_drives) do |page_token| 338 | drive_service.list_teamdrives( 339 | q: 'organizerCount = 0', 340 | fields: 'nextPageToken, teamDrives(id, name)', 341 | use_domain_admin_access: true, 342 | page_token: page_token 343 | ) 344 | end 345 | 346 | for team_drive in team_drives 347 | puts "Found Team Drive without organizer: #{team_drive.name} #{team_drive.id}" 348 | permission = drive_service.create_permission(team_drive.id, 349 | new_organizer_permission, 350 | use_domain_admin_access: true, 351 | supports_team_drives: true, 352 | fields: 'id') 353 | puts "Added organizer permission: {permission.id}" 354 | end 355 | # [END drive_recover_team_drives] 356 | return team_drives.to_a 357 | end 358 | end 359 | -------------------------------------------------------------------------------- /drive/snippets/lib/team_drive_snippets.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | require 'google/apis/drive_v3' 16 | require 'securerandom' 17 | 18 | class TeamDriveSnippets 19 | def initialize(service) 20 | @service = service 21 | end 22 | 23 | def drive_service 24 | @service 25 | end 26 | 27 | def create_team_drive 28 | # [START drive_create_team_drive] 29 | team_drive_metadata = { 30 | name: 'Project Resources' 31 | } 32 | request_id = SecureRandom.uuid 33 | team_drive = drive_service.create_teamdrive(request_id, 34 | team_drive_metadata, 35 | fields: 'id') 36 | puts "Team Drive Id: #{team_drive.id}" 37 | # [END drive_create_team_drive] 38 | team_drive.id 39 | end 40 | 41 | def recover_team_drives(real_user) 42 | # [START drive_recover_team_drives] 43 | # Find all Team Drives without an organizer and add one. 44 | # Note: This example does not capture all cases. Team Drives 45 | # that have an empty group as the sole organizer, or an 46 | # organizer outside the organization are not captured. A 47 | # more exhaustive approach would evaluate each Team Drive 48 | # and the associated permissions and groups to ensure an active 49 | # organizer is assigned. 50 | new_organizer_permission = { 51 | type: 'user', 52 | role: 'organizer', 53 | email_address: 'user@example.com' 54 | } 55 | # [START_EXCLUDE silent] 56 | new_organizer_permission[:email_address] = real_user 57 | # [END_EXCLUDE] 58 | 59 | team_drives = drive_service.fetch_all(items: :team_drives) do |page_token| 60 | drive_service.list_teamdrives( 61 | q: 'organizerCount = 0', 62 | fields: 'nextPageToken, teamDrives(id, name)', 63 | use_domain_admin_access: true, 64 | page_token: page_token 65 | ) 66 | end 67 | 68 | for team_drive in team_drives 69 | puts "Found Team Drive without organizer: #{team_drive.name} #{team_drive.id}" 70 | permission = drive_service.create_permission(team_drive.id, 71 | new_organizer_permission, 72 | use_domain_admin_access: true, 73 | supports_team_drives: true, 74 | fields: 'id') 75 | puts "Added organizer permission: {permission.id}" 76 | end 77 | # [END drive_recover_team_drives] 78 | return team_drives.to_a 79 | end 80 | end 81 | -------------------------------------------------------------------------------- /drive/snippets/spec/drive_snippets_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | require "spec_helper" 16 | require "drive_snippets" 17 | 18 | RSpec.describe DriveSnippets do 19 | include TestHelpers 20 | 21 | before :all do 22 | @snippets = DriveSnippets.new build_service 23 | reset 24 | end 25 | 26 | after :all do 27 | cleanup_files 28 | end 29 | 30 | it "should upload a photo" do 31 | file_id = @snippets.upload_basic 32 | expect(file_id).to_not be_nil 33 | delete_file_on_cleanup file_id 34 | end 35 | 36 | it "should upload a revision" do 37 | file_id = @snippets.upload_basic 38 | file_id = @snippets.upload_revision file_id 39 | expect(file_id).to_not be_nil 40 | delete_file_on_cleanup file_id 41 | end 42 | 43 | it "should upload to a folder" do 44 | folder_id = @snippets.create_folder 45 | delete_file_on_cleanup folder_id 46 | file_id = @snippets.upload_to_folder folder_id 47 | expect(file_id).to_not be_nil 48 | delete_file_on_cleanup file_id 49 | end 50 | 51 | it "should upload and convert" do 52 | file_id = @snippets.upload_with_conversion 53 | expect(file_id).to_not be_nil 54 | delete_file_on_cleanup file_id 55 | end 56 | 57 | it "should export a PDF" do 58 | file_id = create_test_document 59 | content = @snippets.export_pdf file_id 60 | content = content.string 61 | expect(content.length).to_not be 0 62 | expect(content.slice(0, 4)).to eq "%PDF" 63 | end 64 | 65 | it "should download a file" do 66 | file_id = create_test_blob 67 | content = @snippets.download_file file_id 68 | content = content.string 69 | expect(content.length).to_not eq 0 70 | expect(content[0]).to eq "\xFF" 71 | expect(content[1]).to eq "\xD8" 72 | end 73 | 74 | it "should create a short cut" do 75 | file_id = @snippets.create_shortcut 76 | expect(file_id).to_not be_nil 77 | delete_file_on_cleanup file_id 78 | end 79 | 80 | it "should update the modified time" do 81 | file_id = create_test_blob 82 | now = DateTime.now 83 | now = DateTime.new(now.year, now.month, now.day, now.hour, now.minute, 84 | now.second) 85 | modified_time = @snippets.touch_file file_id, now 86 | expect(modified_time).to eq(now) 87 | end 88 | 89 | it "should create a folder" do 90 | file_id = @snippets.create_folder 91 | expect(file_id).to_not be_nil 92 | delete_file_on_cleanup file_id 93 | end 94 | 95 | it "should move a file to a folder" do 96 | folder_id = @snippets.create_folder 97 | delete_file_on_cleanup folder_id 98 | file_id = create_test_blob 99 | parents = @snippets.move_file_to_folder file_id, folder_id 100 | expect(parents).to include folder_id 101 | expect(parents.length).to eq 1 102 | end 103 | 104 | it "should search files" do 105 | create_test_blob 106 | files = @snippets.search_files 107 | expect(files.length).to_not eq 0 108 | end 109 | 110 | it "should share files" do 111 | file_id = create_test_blob 112 | ids = @snippets.share_file file_id, "user@test.appsdevtesting.com", "test.appsdevtesting.com" 113 | expect(ids.length).to eq 2 114 | end 115 | 116 | it "should get the starting page token" do 117 | token = @snippets.fetch_start_page_token 118 | expect(token).to_not be_nil 119 | end 120 | 121 | it "should fetch changes" do 122 | start_token = @snippets.fetch_start_page_token 123 | create_test_blob 124 | token = @snippets.fetch_changes start_token 125 | expect(token).to_not be_nil 126 | expect(token).to_not eq start_token 127 | end 128 | 129 | it "should upload a photo" do 130 | file_id = @snippets.upload_app_data 131 | expect(file_id).to_not be_nil 132 | delete_file_on_cleanup file_id 133 | end 134 | 135 | it "should list files" do 136 | file_id = @snippets.upload_app_data 137 | delete_file_on_cleanup file_id 138 | files = @snippets.list_app_data 139 | expect(files.length).to_not eq 0 140 | end 141 | 142 | it "should fetch the app data folder" do 143 | file_id = @snippets.fetch_app_data_folder 144 | expect(file_id).to_not be_nil 145 | end 146 | end 147 | -------------------------------------------------------------------------------- /drive/snippets/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | spec_dir = __dir__ 16 | root_dir = File.expand_path File.join(spec_dir, "..") 17 | lib_dir = File.expand_path File.join(root_dir, "lib") 18 | 19 | $LOAD_PATH.unshift spec_dir 20 | $LOAD_PATH.unshift lib_dir 21 | $LOAD_PATH.uniq! 22 | 23 | require "rspec" 24 | require "googleauth" 25 | require "google/apis/drive_v3" 26 | 27 | # Drive Test Helpers 28 | module TestHelpers 29 | # Builds a DriveService with a service account 30 | def build_service 31 | drive = Google::Apis::DriveV3::DriveService.new 32 | drive.authorization = Google::Auth.get_application_default( 33 | [Google::Apis::DriveV3::AUTH_DRIVE, 34 | Google::Apis::DriveV3::AUTH_DRIVE_APPDATA] 35 | ) 36 | drive 37 | end 38 | 39 | # Builds a DriveService with an OAuth client ID 40 | def build_oauth_service 41 | # TODO 42 | end 43 | 44 | def drive_service 45 | @drive_service ||= build_service 46 | end 47 | 48 | def reset 49 | @files_to_delete = [] 50 | end 51 | 52 | def cleanup_files 53 | @files_to_delete ||= [] 54 | return if @files_to_delete.empty? 55 | 56 | drive_service.batch do 57 | @files_to_delete.each do |file_id| 58 | puts "Deleting file #{file_id}" 59 | drive_service.delete_file file_id do |res, err| 60 | # Ignore errors... 61 | end 62 | end 63 | end 64 | end 65 | 66 | def delete_file_on_cleanup file_id 67 | @files_to_delete << file_id 68 | end 69 | 70 | def create_test_blob 71 | file_metadata = { name: "photo.jpg" } 72 | file = drive_service.create_file(file_metadata, 73 | upload_source: "files/photo.jpg", 74 | content_type: "image/jpeg") 75 | delete_file_on_cleanup file.id 76 | file.id 77 | end 78 | 79 | def create_test_document 80 | file_metadata = { 81 | name: "Test Document", 82 | mime_type: "application/vnd.google-apps.document" 83 | } 84 | file = drive_service.create_file(file_metadata, 85 | upload_source: "files/document.txt", 86 | content_type: "text/plain") 87 | delete_file_on_cleanup file.id 88 | file.id 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /drive/snippets/spec/team_drive_snippets_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | require "spec_helper" 16 | require "team_drive_snippets" 17 | 18 | RSpec.describe TeamDriveSnippets do 19 | include TestHelpers 20 | 21 | before :all do 22 | @snippets = TeamDriveSnippets.new build_oauth_service 23 | reset 24 | end 25 | 26 | after service.run_script do 27 | cleanup_files 28 | end 29 | 30 | # it "should create a team drive" do 31 | # id = @snippets.create_team_drive 32 | # expect(id).to_not be_nil 33 | # drive_service.delete_teamdrive(id) 34 | # end 35 | 36 | # it "should recover an orphaned team drive" do 37 | # id = self.create_orphaned_team_drive 38 | # team_drives = @snippets.recover_team_drives("sbazyl@test.appsdevtesting.com") 39 | # expect(team_drives.length).to_not eq 0 40 | # drive_service.delete_teamdrive(id) 41 | # end 42 | 43 | def create_orphaned_team_drive 44 | team_drive_id = @snippets.create_team_drive 45 | permissions = drive_service.list_permissions(team_drive_id, 46 | supports_team_drives: true) 47 | permissions.permissions.each do |permission| 48 | drive_service.delete_permission(team_drive_id, 49 | permission.id, 50 | supports_team_drives: true) 51 | end 52 | team_drive_id 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /drive/snippets/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | export GOOGLE_APPLICATION_CREDENTIALS="$(pwd)/../../application_credentials.json"; 17 | rspec 18 | -------------------------------------------------------------------------------- /gmail/quickstart/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /gmail/quickstart/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /gmail/quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Gmail Ruby Quickstart 2 | 3 | Complete the steps described in the [Gmail Ruby Quickstart](https://developers.google.com/gmail/api/quickstart/ruby), and in about five minutes you'll have a simple Ruby command-line application that makes requests to the Gmail API. 4 | 5 | ## Install 6 | 7 | `bundle install` 8 | 9 | ## Run 10 | 11 | `ruby quickstart.rb` 12 | -------------------------------------------------------------------------------- /gmail/quickstart/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START gmail_quickstart] 15 | require "google/apis/gmail_v1" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Gmail API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = Google::Apis::GmailV1::AUTH_GMAIL_READONLY 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | # Initialize the API 54 | service = Google::Apis::GmailV1::GmailService.new 55 | service.client_options.application_name = APPLICATION_NAME 56 | service.authorization = authorize 57 | 58 | # Show the user's labels 59 | user_id = "me" 60 | result = service.list_user_labels user_id 61 | puts "Labels:" 62 | puts "No labels found" if result.labels.empty? 63 | result.labels.each { |label| puts "- #{label.name}" } 64 | # [END gmail_quickstart] 65 | -------------------------------------------------------------------------------- /people/quickstart/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /people/quickstart/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /people/quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Google People API Ruby Quickstart 2 | 3 | Complete the steps described in the [Google People API Ruby Quickstart](https://developers.google.com/people/quickstart/ruby), and in about five minutes you'll have a simple Ruby command-line application that makes requests to the Google People API. 4 | 5 | ## Install 6 | 7 | `bundle install` 8 | 9 | ## Run 10 | 11 | `ruby quickstart.rb` 12 | 13 | -------------------------------------------------------------------------------- /people/quickstart/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START people_quickstart] 15 | require "google/apis/people_v1" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Google People API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = Google::Apis::PeopleV1::AUTH_CONTACTS_READONLY 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | # Initialize the API 54 | service = Google::Apis::PeopleV1::PeopleServiceService.new 55 | service.client_options.application_name = APPLICATION_NAME 56 | service.authorization = authorize 57 | 58 | # Fetch the next 10 events for the user 59 | response = service.list_person_connections( 60 | "people/me", 61 | page_size: 10, 62 | person_fields: "names,emailAddresses" 63 | ) 64 | 65 | puts "Connection names:" 66 | puts "No connections found" if response.connections.empty? 67 | response.connections.each do |person| 68 | names = person.names 69 | if names.nil? 70 | puts "No names found for connection" 71 | else 72 | puts "- #{names[0].display_name}" 73 | end 74 | end 75 | # [END people_quickstart] 76 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /sheets/quickstart/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /sheets/quickstart/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /sheets/quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Google Sheets Ruby Quickstart 2 | 3 | Complete the steps described in the [Google Sheets Ruby Quickstart](https://developers.google.com/sheets/api/quickstart/ruby), and in about five minutes you'll have a simple Ruby command-line application that makes requests to the Google Sheets API. 4 | 5 | ## Install 6 | 7 | `bundle install` 8 | 9 | ## Run 10 | 11 | `ruby quickstart.rb` 12 | -------------------------------------------------------------------------------- /sheets/quickstart/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START sheets_quickstart] 15 | require "google/apis/sheets_v4" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Google Sheets API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = Google::Apis::SheetsV4::AUTH_SPREADSHEETS_READONLY 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | # Initialize the API 54 | service = Google::Apis::SheetsV4::SheetsService.new 55 | service.client_options.application_name = APPLICATION_NAME 56 | service.authorization = authorize 57 | 58 | # Prints the names and majors of students in a sample spreadsheet: 59 | # https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit 60 | spreadsheet_id = "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms" 61 | range = "Class Data!A2:E" 62 | response = service.get_spreadsheet_values spreadsheet_id, range 63 | puts "Name, Major:" 64 | puts "No data found." if response.values.empty? 65 | response.values.each do |row| 66 | # Print columns A and E, which correspond to indices 0 and 4. 67 | puts "#{row[0]}, #{row[4]}" 68 | end 69 | # [END sheets_quickstart] 70 | -------------------------------------------------------------------------------- /sheets/snippets/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~>0.11" 18 | gem "rspec", "~> 3.0" 19 | -------------------------------------------------------------------------------- /sheets/snippets/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | command -v rbenv >/dev/null 2>&1 || { echo >&2 "rbenv required, aborting."; exit 1; } 17 | command -v ruby-build >/dev/null 2>&1 || { echo >&2 "ruby-build required, aborting."; exit 1; } 18 | rbenv install -s 19 | gem install bundler 20 | bundler install 21 | -------------------------------------------------------------------------------- /sheets/snippets/lib/spreadsheet_snippets.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | require 'google/apis/sheets_v4' 16 | 17 | class SpreadsheetSnippets 18 | def initialize(service) 19 | @service = service 20 | end 21 | 22 | def service 23 | @service 24 | end 25 | 26 | def create 27 | # [START sheets_create] 28 | spreadsheet = { 29 | properties: { 30 | title: 'Sales Report' 31 | } 32 | } 33 | spreadsheet = service.create_spreadsheet(spreadsheet, 34 | fields: 'spreadsheetId') 35 | puts "Spreadsheet ID: #{spreadsheet.spreadsheet_id}" 36 | # [END sheets_create] 37 | spreadsheet.spreadsheet_id 38 | end 39 | 40 | def batch_update(spreadsheet_id, title, find, replacement) 41 | # [START sheets_batch_update] 42 | requests = [] 43 | # Change the name of sheet ID '0' (the default first sheet on every 44 | # spreadsheet) 45 | requests.push({ 46 | update_sheet_properties: { 47 | properties: { sheet_id: 0, title: 'New Sheet Name' }, 48 | fields: 'title' 49 | } 50 | }) 51 | # Find and replace text 52 | requests.push({ 53 | find_replace: { 54 | find: find, 55 | replacement: replacement, 56 | all_sheets: true 57 | } 58 | }) 59 | # Add additional requests (operations) ... 60 | 61 | body = { requests: requests } 62 | result = service.batch_update_spreadsheet(spreadsheet_id, body, {}) 63 | find_replace_response = result.replies[1].find_replace 64 | puts "#{find_replace_response.occurrences_changed} replacements made." 65 | # [END sheets_batch_update] 66 | result 67 | end 68 | 69 | def get_values(spreadsheet_id, range_name) 70 | # [START sheets_get_values] 71 | result = service.get_spreadsheet_values(spreadsheet_id, range_name) 72 | num_rows = result.values ? result.values.length : 0 73 | puts "#{num_rows} rows received." 74 | # [END sheets_get_values] 75 | result 76 | end 77 | 78 | def batch_get_values(spreadsheet_id, range) 79 | # [START sheets_batch_get_values] 80 | range_names = [ 81 | # Range names ... 82 | ] 83 | # [START_EXCLUDE silent] 84 | range_names = range 85 | # [END_EXCLUDE] 86 | result = service.batch_get_spreadsheet_values(spreadsheet_id, 87 | ranges: range_names) 88 | puts "#{result.value_ranges.length} ranges retrieved." 89 | # [END sheets_batch_get_values] 90 | result 91 | end 92 | 93 | def update_values(spreadsheet_id, range_name, value_input_option, _values) 94 | # [START sheets_update_values] 95 | values = [ 96 | [ 97 | # Cell values ... 98 | ] 99 | # Additional rows ... 100 | ] 101 | # [START_EXCLUDE silent] 102 | values = _values 103 | # [END_EXCLUDE] 104 | data = [ 105 | { 106 | range: range_name, 107 | values: values 108 | }, 109 | # Additional ranges to update ... 110 | ] 111 | value_range_object = Google::Apis::SheetsV4::ValueRange.new(range: range_name, 112 | values: values) 113 | result = service.update_spreadsheet_value(spreadsheet_id, 114 | range_name, 115 | value_range_object, 116 | value_input_option: value_input_option) 117 | puts "#{result.updated_cells} cells updated." 118 | # [END sheets_update_values] 119 | result 120 | end 121 | 122 | def batch_update_values(spreadsheet_id, range_name, value_input_option, _values) 123 | # [START sheets_batch_update_values] 124 | values = [ 125 | [ 126 | # Cell values ... 127 | ] 128 | # Additional rows ... 129 | ] 130 | # [START_EXCLUDE silent] 131 | values = _values 132 | # [END_EXCLUDE] 133 | data = [ 134 | { 135 | range: range_name, 136 | values: values 137 | }, 138 | # Additional ranges to update ... 139 | ] 140 | batch_update_values = Google::Apis::SheetsV4::BatchUpdateValuesRequest.new( 141 | data: data, 142 | value_input_option: value_input_option 143 | ) 144 | result = service.batch_update_values(spreadsheet_id, batch_update_values) 145 | puts "#{result.total_updated_cells} cells updated." 146 | # [END sheets_batch_update_values] 147 | result 148 | end 149 | 150 | def append_values(spreadsheet_id, range_name, value_input_option, _values) 151 | # [START sheets_append_values] 152 | values = [ 153 | [ 154 | # Cell values ... 155 | ], 156 | # Additional rows ... 157 | ] 158 | # [START_EXCLUDE silent] 159 | values = _values 160 | # [END_EXCLUDE] 161 | value_range = Google::Apis::SheetsV4::ValueRange.new(values: values) 162 | result = service.append_spreadsheet_value(spreadsheet_id, 163 | range_name, 164 | value_range, 165 | value_input_option: value_input_option) 166 | puts "#{result.updates.updated_cells} cells appended." 167 | # [END sheets_append_values] 168 | result 169 | end 170 | 171 | def pivot_tables(spreadsheet_id) 172 | # Create two sheets for our pivot table. 173 | body = { 174 | requests: [{ 175 | add_sheet: {} 176 | }, { 177 | add_sheet: {} 178 | }] 179 | } 180 | batch_update_response = service.batch_update_spreadsheet(spreadsheet_id, 181 | body, 182 | {}) 183 | source_sheet_id = batch_update_response.replies[0].add_sheet.properties.sheet_id 184 | target_sheet_id = batch_update_response.replies[1].add_sheet.properties.sheet_id 185 | # [START sheets_pivot_tables] 186 | requests = [{ 187 | update_cells: { 188 | rows: { 189 | values: [ 190 | { 191 | pivot_table: { 192 | source: { 193 | sheet_id: source_sheet_id, 194 | start_row_index: 0, 195 | start_column_index: 0, 196 | end_row_index: 20, 197 | end_column_index: 7 198 | }, 199 | rows: [ 200 | { 201 | source_column_offset: 1, 202 | show_totals: true, 203 | sort_order: 'ASCENDING', 204 | }, 205 | ], 206 | columns: [ 207 | { 208 | source_column_offset: 4, 209 | sort_order: 'ASCENDING', 210 | show_totals: true, 211 | } 212 | ], 213 | values: [ 214 | { 215 | summarize_function: 'COUNTA', 216 | source_column_offset: 4 217 | } 218 | ], 219 | value_layout: 'HORIZONTAL' 220 | } 221 | } 222 | ] 223 | }, 224 | start: { 225 | sheet_id: target_sheet_id, 226 | row_index: 0, 227 | column_index: 0 228 | }, 229 | fields: 'pivotTable' 230 | } 231 | }] 232 | result = service.batch_update_spreadsheet(spreadsheet_id, body, {}) 233 | # [END sheets_pivot_tables] 234 | result 235 | end 236 | 237 | def conditional_formatting(spreadsheet_id) 238 | # [START sheets_conditional_formatting] 239 | my_range = { 240 | sheet_id: 0, 241 | start_row_index: 1, 242 | end_row_index: 11, 243 | start_column_index: 0, 244 | end_column_index: 4 245 | } 246 | requests = [{ 247 | add_conditional_format_rule: { 248 | rule: { 249 | ranges: [my_range], 250 | boolean_rule: { 251 | condition: { 252 | type: 'CUSTOM_FORMULA', 253 | values: [{ user_entered_value: '=GT($D2,median($D$2:$D$11))' }] 254 | }, 255 | format: { 256 | text_format: { foreground_color: { red: 0.8 } } 257 | } 258 | } 259 | }, 260 | index: 0 261 | } 262 | }, { 263 | add_conditional_format_rule: { 264 | rule: { 265 | ranges: [my_range], 266 | boolean_rule: { 267 | condition: { 268 | type: 'CUSTOM_FORMULA', 269 | values: [{ user_entered_value: '=LT($D2,median($D$2:$D$11))' }] 270 | }, 271 | format: { 272 | background_color: { red: 1, green: 0.4, blue: 0.4 } 273 | } 274 | } 275 | }, 276 | index: 0 277 | } 278 | }] 279 | body = { 280 | requests: requests 281 | } 282 | batch_update = Google::Apis::SheetsV4::BatchUpdateSpreadsheetRequest.new 283 | batch_update.requests = requests 284 | result = service.batch_update_spreadsheet(spreadsheet_id, batch_update) 285 | puts "#{result.replies.length} cells updated." 286 | # [END sheets_conditional_formatting] 287 | result 288 | end 289 | end 290 | -------------------------------------------------------------------------------- /sheets/snippets/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | spec_dir = __dir__ 16 | root_dir = File.expand_path File.join(spec_dir, "..") 17 | lib_dir = File.expand_path File.join(root_dir, "lib") 18 | 19 | $LOAD_PATH.unshift spec_dir 20 | $LOAD_PATH.unshift lib_dir 21 | $LOAD_PATH.uniq! 22 | 23 | require "rspec" 24 | require "googleauth" 25 | require "google/apis/drive_v3" 26 | require "google/apis/sheets_v4" 27 | 28 | # Test helpers 29 | module TestHelpers 30 | def build_service 31 | sheets = Google::Apis::SheetsV4::SheetsService.new 32 | sheets.authorization = Google::Auth.get_application_default( 33 | [Google::Apis::DriveV3::AUTH_DRIVE] 34 | ) 35 | sheets 36 | end 37 | 38 | def build_drive_service 39 | drive = Google::Apis::DriveV3::DriveService.new 40 | drive.authorization = Google::Auth.get_application_default( 41 | [Google::Apis::DriveV3::AUTH_DRIVE] 42 | ) 43 | drive 44 | end 45 | 46 | def service 47 | @service ||= build_service 48 | end 49 | 50 | def drive_service 51 | @drive_service ||= build_drive_service 52 | end 53 | 54 | def reset 55 | @files_to_delete = [] 56 | end 57 | 58 | def cleanup_files 59 | @files_to_delete ||= [] 60 | return if @files_to_delete.empty? 61 | 62 | drive_service.batch do 63 | @files_to_delete.each do |file_id| 64 | puts "Deleting file #{file_id}" 65 | drive_service.delete_file file_id do |res, err| 66 | # Ignore errors... 67 | end 68 | end 69 | end 70 | end 71 | 72 | def delete_file_on_cleanup file_id 73 | @files_to_delete << file_id 74 | end 75 | 76 | def create_test_spreadsheet 77 | spreadsheet = { 78 | properties: { 79 | title: "Test Spreadsheet" 80 | } 81 | } 82 | spreadsheet = service.create_spreadsheet(spreadsheet, 83 | fields: "spreadsheetId") 84 | delete_file_on_cleanup spreadsheet.spreadsheet_id 85 | spreadsheet.spreadsheet_id 86 | end 87 | 88 | def populate_values spreadsheet_id 89 | body = { 90 | requests: [{ 91 | repeat_cell: { 92 | range: { 93 | sheet_id: 0, 94 | start_row_index: 0, 95 | end_row_index: 10, 96 | start_column_index: 0, 97 | end_column_index: 10 98 | }, 99 | cell: { 100 | user_entered_value: { 101 | string_value: "Hello" 102 | } 103 | }, 104 | fields: "userEnteredValue" 105 | } 106 | }] 107 | } 108 | service.batch_update_spreadsheet(spreadsheet_id, body, {}) 109 | end 110 | end 111 | -------------------------------------------------------------------------------- /sheets/snippets/spec/spreadsheet_snippets_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | require "spec_helper" 16 | require "spreadsheet_snippets" 17 | 18 | VALUES_2D = [ 19 | %w[A B], 20 | %w[C D] 21 | ].freeze 22 | 23 | RSpec.describe SpreadsheetSnippets do 24 | include TestHelpers 25 | 26 | before :all do 27 | @snippets = SpreadsheetSnippets.new build_service 28 | reset 29 | end 30 | 31 | after :all do 32 | cleanup_files 33 | end 34 | 35 | it "should create a spreadsheet" do 36 | id = @snippets.create 37 | expect(id).to_not be_nil 38 | delete_file_on_cleanup id 39 | end 40 | 41 | it "should batch update a spreadsheet" do 42 | id = create_test_spreadsheet 43 | populate_values id 44 | result = @snippets.batch_update id, "New Title", "Hello", "Goodbye" 45 | expect(result.replies.length).to eq(2) 46 | find_replace_response = result.replies[1].find_replace 47 | expect(find_replace_response.occurrences_changed).to eq(100) 48 | end 49 | 50 | it "should get values" do 51 | id = create_test_spreadsheet 52 | populate_values id 53 | result = @snippets.get_values id, "A1:C2" 54 | expect(result).to_not be_nil 55 | values = result.values 56 | expect(values).to_not be_nil 57 | expect(values.length).to eq(2) 58 | expect(values[0].length).to eq(3) 59 | end 60 | 61 | it "should batch get values" do 62 | id = create_test_spreadsheet 63 | populate_values id 64 | result = @snippets.batch_get_values id, ["A1:A3", "B1:C1"] 65 | value_ranges = result.value_ranges 66 | expect(result).to_not be_nil 67 | expect(value_ranges.length).to eq(2) 68 | values = value_ranges[0].values 69 | expect(values.length).to eq(3) 70 | end 71 | 72 | it "should update values" do 73 | id = create_test_spreadsheetgspe 74 | result = @snippets.update_values id, "A1:B2", "USER_ENTERED", VALUES_2D 75 | expect(result).to_not be_nil 76 | expect(result.updated_rows).to eq(2) 77 | expect(result.updated_columns).to eq(2) 78 | expect(result.updated_cells).to eq(4) 79 | end 80 | 81 | it "should batch update values" do 82 | id = create_test_spreadsheet 83 | result = @snippets.batch_update_values id, "A1:B2", "USER_ENTERED", VALUES_2D 84 | expect(result).to_not be_nil 85 | responses = result.responses 86 | expect(responses.length).to eq(1) 87 | expect(responses[0].updated_rows).to eq(2) 88 | expect(responses[0].updated_columns).to eq(2) 89 | end 90 | 91 | it "should append values" do 92 | id = create_test_spreadsheet 93 | populate_values id 94 | result = @snippets.append_values id, "Sheet1", "USER_ENTERED", VALUES_2D 95 | expect(result).to_not be_nil 96 | expect(result.table_range).to eq("Sheet1!A1:J10") 97 | updates = result.updates 98 | expect(updates.updated_range).to eq("Sheet1!A11:B12") 99 | expect(updates.updated_rows).to eq(2) 100 | expect(updates.updated_columns).to eq(2) 101 | expect(updates.updated_cells).to eq(4) 102 | end 103 | 104 | it "should create pivot tables" do 105 | id = create_test_spreadsheet 106 | populate_values id 107 | result = @snippets.pivot_tables id 108 | expect(result).to_not be_nil 109 | end 110 | 111 | it "should conditionally format" do 112 | id = create_test_spreadsheet 113 | populate_values id 114 | result = @snippets.conditional_formatting id 115 | expect(result.spreadsheet_id).to eq(id) 116 | expect(result.replies.length).to eq(2) 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /sheets/snippets/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | export GOOGLE_APPLICATION_CREDENTIALS="$(pwd)/../../application_credentials.json"; 17 | rspec 18 | -------------------------------------------------------------------------------- /slides/quickstart/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /slides/quickstart/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /slides/quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Google Slides Ruby Quickstart 2 | 3 | Complete the steps described in the [Google Slides Ruby Quickstart](https://developers.google.com/slides/quickstart/ruby), and in about five minutes you'll have a simple Ruby command-line application that makes requests to the Google Slides API. 4 | 5 | ## Install 6 | 7 | `bundle install` 8 | 9 | ## Run 10 | 11 | `ruby quickstart.rb` 12 | -------------------------------------------------------------------------------- /slides/quickstart/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START slides_quickstart] 15 | require "google/apis/slides_v1" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Google Slides API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = Google::Apis::SlidesV1::AUTH_PRESENTATIONS_READONLY 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | # Initialize the API 54 | service = Google::Apis::SlidesV1::SlidesService.new 55 | service.client_options.application_name = APPLICATION_NAME 56 | service.authorization = authorize 57 | 58 | # Prints the number of slides and elements in a sample presentation: 59 | # https://docs.google.com/presentation/d/1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc/edit 60 | presentation_id = "1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc" 61 | presentation = service.get_presentation presentation_id 62 | puts "The presentation contains #{presentation.slides.count} slides:" 63 | presentation.slides.each_with_index do |slide, i| 64 | puts "- Slide \##{i + 1} contains #{slide.page_elements.count} elements." 65 | end 66 | # [END slides_quickstart] 67 | -------------------------------------------------------------------------------- /slides/snippets/.gitignore: -------------------------------------------------------------------------------- 1 | files 2 | .idea/ 3 | -------------------------------------------------------------------------------- /slides/snippets/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.9" 18 | gem "rspec", "~> 3.0" 19 | -------------------------------------------------------------------------------- /slides/snippets/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.5.2) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | diff-lcs (1.3) 9 | faraday (0.13.1) 10 | multipart-post (>= 1.2, < 3) 11 | google-api-client (0.17.1) 12 | addressable (~> 2.5, >= 2.5.1) 13 | googleauth (>= 0.5, < 0.7.0) 14 | httpclient (>= 2.8.1, < 3.0) 15 | mime-types (~> 3.0) 16 | representable (~> 3.0) 17 | retriable (>= 2.0, < 4.0) 18 | googleauth (0.6.2) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | logging (~> 2.0) 22 | memoist (~> 0.12) 23 | multi_json (~> 1.11) 24 | os (~> 0.9) 25 | signet (~> 0.7) 26 | httpclient (2.8.3) 27 | jwt (1.5.6) 28 | little-plugger (1.1.4) 29 | logging (2.2.2) 30 | little-plugger (~> 1.1) 31 | multi_json (~> 1.10) 32 | memoist (0.16.0) 33 | mime-types (3.1) 34 | mime-types-data (~> 3.2015) 35 | mime-types-data (3.2016.0521) 36 | multi_json (1.12.2) 37 | multipart-post (2.0.0) 38 | os (0.9.6) 39 | public_suffix (2.0.5) 40 | representable (3.0.4) 41 | declarative (< 0.1.0) 42 | declarative-option (< 0.2.0) 43 | uber (< 0.2.0) 44 | retriable (3.1.1) 45 | rspec (3.6.0) 46 | rspec-core (~> 3.6.0) 47 | rspec-expectations (~> 3.6.0) 48 | rspec-mocks (~> 3.6.0) 49 | rspec-core (3.6.0) 50 | rspec-support (~> 3.6.0) 51 | rspec-expectations (3.6.0) 52 | diff-lcs (>= 1.2.0, < 2.0) 53 | rspec-support (~> 3.6.0) 54 | rspec-mocks (3.6.0) 55 | diff-lcs (>= 1.2.0, < 2.0) 56 | rspec-support (~> 3.6.0) 57 | rspec-support (3.6.0) 58 | signet (0.8.1) 59 | addressable (~> 2.3) 60 | faraday (~> 0.9) 61 | jwt (>= 1.5, < 3.0) 62 | multi_json (~> 1.10) 63 | uber (0.1.0) 64 | 65 | PLATFORMS 66 | ruby 67 | 68 | DEPENDENCIES 69 | google-api-client (~> 0.9) 70 | rspec (~> 3.0) 71 | 72 | BUNDLED WITH 73 | 1.16.1 74 | -------------------------------------------------------------------------------- /slides/snippets/lib/file_snippets.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | require 'google/apis/drive_v3' 16 | require 'google/apis/slides_v1' 17 | 18 | class FileSnippets 19 | def initialize(drive_service, slides_service, sheets_service) 20 | @drive_service = drive_service 21 | @slides_service = slides_service 22 | @sheets_service = sheets_service 23 | end 24 | 25 | def drive_service 26 | @drive_service 27 | end 28 | 29 | def slides_service 30 | @slides_service 31 | end 32 | 33 | def sheets_service 34 | @sheets_service 35 | end 36 | 37 | def create_presentation(title = 'Title') 38 | # [START slides_create_presentation] 39 | body = Google::Apis::SlidesV1::Presentation.new 40 | body.title = title 41 | presentation = slides_service.create_presentation(body) 42 | puts "Created presentation with ID: #{presentation.presentation_id}" 43 | # [END slides_create_presentation] 44 | presentation 45 | end 46 | 47 | def copy_presentation(presentation_id, copy_title) 48 | # [START slides_copy_presentation] 49 | body = Google::Apis::SlidesV1::Presentation.new 50 | body.title = copy_title 51 | drive_response = drive_service.copy_file(presentation_id, body) 52 | puts drive_response 53 | presentation_copy_id = drive_response.id 54 | # [END slides_copy_presentation] 55 | presentation_copy_id 56 | end 57 | 58 | def create_slide(presentation_id, page_id) 59 | # [START slides_create_slide] 60 | body = Google::Apis::SlidesV1::Presentation.new 61 | requests = [{ 62 | create_slide: { 63 | object_id_prop: page_id, 64 | insertion_index: '1', 65 | slide_layout_reference: { 66 | predefined_layout: 'TITLE_AND_TWO_COLUMNS' 67 | } 68 | } 69 | }] 70 | 71 | # If you wish to populate the slide with elements, add element create requests here, 72 | # using the page_id. 73 | 74 | # Execute the request. 75 | req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new(requests: requests) 76 | response = slides_service.batch_update_presentation(presentation_id, req) 77 | create_slide_response = response.replies[0].create_slide 78 | puts "Created slide with ID: #{create_slide_response.object_id}" 79 | # [END slides_create_slide] 80 | create_slide_response 81 | end 82 | 83 | def create_textbox_with_text(presentation_id, page_id) 84 | # [START slides_create_textbox_with_text] 85 | # Create a new square textbox, using the supplied element ID. 86 | element_id = 'MyTextBox_01' 87 | pt350 = { 88 | magnitude: '350', 89 | unit: 'PT' 90 | } 91 | requests = [ 92 | { 93 | create_shape: { 94 | object_id_prop: element_id, 95 | shape_type: 'TEXT_BOX', 96 | element_properties: { 97 | page_object_id: page_id, 98 | size: { 99 | height: pt350, 100 | width: pt350 101 | }, 102 | transform: { 103 | scale_x: '1', 104 | scale_y: '1', 105 | translate_x: '350', 106 | translate_y: '100', 107 | unit: 'PT' 108 | } 109 | } 110 | } 111 | }, 112 | # Insert text into the box, using the supplied element ID. 113 | { 114 | insert_text: { 115 | object_id_prop: element_id, 116 | insertion_index: 0, 117 | text: 'New Box Text Inserted!' 118 | } 119 | } 120 | ] 121 | 122 | # Execute the request. 123 | req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new(requests: requests) 124 | response = slides_service.batch_update_presentation( 125 | presentation_id, 126 | req 127 | ) 128 | create_shape_response = response.replies[0].create_shape 129 | puts "Created textbox with ID: #{create_shape_response.object_id}" 130 | # [END slides_create_textbox_with_text] 131 | response 132 | end 133 | 134 | def create_image(presentation_id, page_id) 135 | # [START slides_create_image] 136 | # Create a new image, using the supplied object ID, with content downloaded from image_url. 137 | requests = [] 138 | image_id = 'MyImage_01' 139 | emu4M = { 140 | magnitude: '4000000', 141 | unit: 'EMU' 142 | } 143 | requests << { 144 | create_image: { 145 | object_id_prop: image_id, 146 | url: IMAGE_URL, 147 | element_properties: { 148 | page_object_id: page_id, 149 | size: { 150 | height: emu4M, 151 | width: emu4M 152 | }, 153 | transform: { 154 | scale_x: '1', 155 | scale_y: '1', 156 | translate_x: '100000', 157 | translate_y: '100000', 158 | unit: 'EMU' 159 | } 160 | } 161 | } 162 | } 163 | 164 | # Execute the request. 165 | req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new(requests: requests) 166 | response = slides_service.batch_update_presentation( 167 | presentation_id, 168 | req 169 | ) 170 | create_image_response = response.replies[0].create_image 171 | puts "Created image with ID: #{create_image_response.object_id}" 172 | # [END slides_create_image] 173 | response 174 | end 175 | 176 | def text_merging(template_presentation_id, data_spreadsheet_id) 177 | responses = [] 178 | # [START slides_text_merging] 179 | # Use the Sheets API to load data, one record per row. 180 | data_range_notation = 'Customers!A2:M6' 181 | sheets_response = sheets_service.get_spreadsheet_values( 182 | data_spreadsheet_id, 183 | data_range_notation 184 | ) 185 | values = sheets_response.values 186 | 187 | # For each record, create a new merged presentation. 188 | values.each do |row| 189 | customer_name = row[2] # name in column 3 190 | case_description = row[5] # case description in column 6 191 | total_portfolio = row[11] # total portfolio in column 12 192 | 193 | # Duplicate the template presentation using the Drive API. 194 | copy_title = customer_name + ' presentation' 195 | body = Google::Apis::SlidesV1::Presentation.new 196 | body.title = copy_title 197 | drive_response = drive_service.copy_file(template_presentation_id, body) 198 | presentation_copy_id = drive_response.id 199 | 200 | # Create the text merge (replace_all_text) requests for this presentation. 201 | requests = [] << { 202 | replace_all_text: { 203 | contains_text: { 204 | text: '{{customer-name}}', 205 | match_case: true 206 | }, 207 | replace_text: customer_name 208 | } 209 | } << { 210 | replace_all_text: { 211 | contains_text: { 212 | text: '{{case-description}}', 213 | match_case: true 214 | }, 215 | replace_text: case_description 216 | } 217 | } << { 218 | replace_all_text: { 219 | contains_text: { 220 | text: '{{total-portfolio}}', 221 | match_case: true 222 | }, 223 | replace_text: total_portfolio 224 | } 225 | } 226 | 227 | # Execute the requests for this presentation. 228 | req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new(requests: requests) 229 | response = slides_service.batch_update_presentation( 230 | presentation_copy_id, 231 | req 232 | ) 233 | # [START_EXCLUDE silent] 234 | responses << response 235 | # [END_EXCLUDE silent] 236 | # Count the total number of replacements made. 237 | num_replacements = 0 238 | response.replies.each do |reply| 239 | num_replacements += reply.replace_all_text.occurrences_changed 240 | end 241 | puts "Created presentation for #{customer_name} with ID: #{presentation_copy_id}" 242 | puts "Replaced #{num_replacements} text instances" 243 | end 244 | # [END slides_text_merging] 245 | responses 246 | end 247 | 248 | def image_merging(template_presentation_id, image_url, customer_name) 249 | logo_url = image_url 250 | customer_graphic_url = image_url 251 | 252 | # [START slides_image_merging] 253 | # Duplicate the template presentation using the Drive API. 254 | copy_title = customer_name + ' presentation' 255 | body = Google::Apis::SlidesV1::Presentation.new 256 | body.title = copy_title 257 | drive_response = drive_service.copy_file(template_presentation_id, body) 258 | presentation_copy_id = drive_response.id 259 | 260 | # Create the image merge (replace_all_shapes_with_image) requests. 261 | requests = [] << { 262 | replace_all_shapes_with_image: { 263 | image_url: logo_url, 264 | replace_method: 'CENTER_INSIDE', 265 | contains_text: { 266 | text: '{{company-logo}}', 267 | match_case: true 268 | } 269 | } 270 | } << { 271 | replace_all_shapes_with_image: { 272 | image_url: customer_graphic_url, 273 | replace_method: 'CENTER_INSIDE', 274 | contains_text: { 275 | text: '{{customer-graphic}}', 276 | match_case: true 277 | } 278 | } 279 | } 280 | 281 | # Execute the requests. 282 | req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new(requests: requests) 283 | response = slides_service.batch_update_presentation( 284 | presentation_copy_id, 285 | req 286 | ) 287 | 288 | # Count the number of replacements made. 289 | num_replacements = 0 290 | response.replies.each do |reply| 291 | num_replacements += reply.replace_all_shapes_with_image.occurrences_changed 292 | end 293 | puts "Created presentation for #{customer_name} with ID: #{presentation_copy_id}" 294 | puts "Replaced #{num_replacements} shapes with images" 295 | # [END slides_image_merging] 296 | response 297 | end 298 | 299 | def simple_text_replace(presentation_id, shape_id, replacement_text) 300 | # [START slides_simple_text_replace] 301 | # Remove existing text in the shape, then insert new text. 302 | requests = [] << { 303 | delete_text: { 304 | object_id_prop: shape_id, 305 | text_range: { 306 | type: 'ALL' 307 | } 308 | } 309 | } << { 310 | insert_text: { 311 | object_id_prop: shape_id, 312 | insertion_index: 0, 313 | text: replacement_text 314 | } 315 | } 316 | 317 | # Execute the requests. 318 | req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new(requests: requests) 319 | response = slides_service.batch_update_presentation( 320 | presentation_id, 321 | req 322 | ) 323 | puts "Replaced text in shape with ID: #{shape_id}" 324 | # [END slides_simple_text_replace] 325 | response 326 | end 327 | 328 | def text_style_update(presentation_id, shape_id) 329 | # [START slides_text_style_update] 330 | # Update the text style so that the first 5 characters are bolded 331 | # and italicized, the next 5 are displayed in blue 14 pt Times 332 | # New Roman font, and the next 5 are hyperlinked. 333 | requests = [] << { 334 | update_text_style: { 335 | object_id_prop: shape_id, 336 | text_range: { 337 | type: 'FIXED_RANGE', 338 | start_index: 0, 339 | end_index: 5 340 | }, 341 | style: { 342 | bold: true, 343 | italic: true 344 | }, 345 | fields: 'bold,italic' 346 | } 347 | } << { 348 | update_text_style: { 349 | object_id_prop: shape_id, 350 | text_range: { 351 | type: 'FIXED_RANGE', 352 | start_index: 5, 353 | end_index: 10 354 | }, 355 | style: { 356 | font_family: 'Times New Roman', 357 | font_size: { 358 | magnitude: 14, 359 | unit: 'PT' 360 | }, 361 | foreground_color: { 362 | opaque_color: { 363 | rgb_color: { 364 | blue: 1.0, 365 | green: 0.0, 366 | red: 0.0 367 | } 368 | } 369 | } 370 | }, 371 | fields: 'foreground_color,font_family,font_size' 372 | } 373 | } << { 374 | update_text_style: { 375 | object_id_prop: shape_id, 376 | text_range: { 377 | type: 'FIXED_RANGE', 378 | start_index: 10, 379 | end_index: 15 380 | }, 381 | style: { 382 | link: { 383 | url: 'www.example.com' 384 | } 385 | }, 386 | fields: 'link' 387 | } 388 | } 389 | 390 | # Execute the requests. 391 | req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new(requests: requests) 392 | response = slides_service.batch_update_presentation(presentation_id, req) 393 | puts "Updated the text style for shape with ID: #{shape_id}" 394 | # [END slides_text_style_update] 395 | response 396 | end 397 | 398 | def create_bulleted_text(presentation_id, shape_id) 399 | # [START slides_create_bulleted_text] 400 | # Add arrow-diamond-disc bullets to all text in the shape. 401 | requests = [] << { 402 | create_paragraph_bullets: { 403 | object_id_prop: shape_id, 404 | text_range: { 405 | type: 'ALL' 406 | }, 407 | bulletPreset: 'BULLET_ARROW_DIAMOND_DISC' 408 | } 409 | } 410 | 411 | # Execute the requests. 412 | req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new(requests: requests) 413 | response = slides_service.batch_update_presentation(presentation_id, req) 414 | puts "Added bullets to text in shape with ID: #{shape_id}" 415 | # [END slides_create_bulleted_text] 416 | response 417 | end 418 | 419 | def create_sheets_chart(presentation_id, page_id, spreadsheet_id, sheet_chart_id) 420 | # [START slides_create_sheets_chart] 421 | # Embed a Sheets chart (indicated by the spreadsheet_id and sheet_chart_id) onto 422 | # a page in the presentation. Setting the linking mode as "LINKED" allows the 423 | # chart to be refreshed if the Sheets version is updated. 424 | emu4M = { 425 | magnitude: 4000000, 426 | unit: 'EMU' 427 | } 428 | presentation_chart_id = 'my_embedded_chart' 429 | requests = [{ 430 | create_sheets_chart: { 431 | object_id_prop: presentation_chart_id, 432 | spreadsheet_id: spreadsheet_id, 433 | chart_id: sheet_chart_id, 434 | linking_mode: 'LINKED', 435 | element_properties: { 436 | page_object_id: page_id, 437 | size: { 438 | height: emu4M, 439 | width: emu4M 440 | }, 441 | transform: { 442 | scale_x: 1, 443 | scale_y: 1, 444 | translate_x: 100000, 445 | translate_y: 100000, 446 | unit: 'EMU' 447 | } 448 | } 449 | } 450 | }] 451 | 452 | # Execute the request. 453 | req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new(requests: requests) 454 | response = slides_service.batch_update_presentation(presentation_id, req) 455 | 456 | puts "Added a linked Sheets chart with ID: #{presentation_chart_id}" 457 | # [END slides_create_sheets_chart] 458 | response 459 | end 460 | 461 | def refresh_sheets_chart(presentation_id, presentation_chart_id) 462 | # [START slides_refresh_sheets_chart] 463 | # Refresh an existing linked Sheets chart embedded in a presentation. 464 | requests = [{ 465 | refresh_sheets_chart: { 466 | object_id_prop: presentation_chart_id 467 | } 468 | }] 469 | 470 | # Execute the request. 471 | req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new(requests: requests) 472 | response = slides_service.batch_update_presentation(presentation_id, req) 473 | 474 | puts "Refreshed a linked Sheets chart with ID: #{presentation_chart_id}" 475 | # [END slides_refresh_sheets_chart] 476 | response 477 | end 478 | end 479 | -------------------------------------------------------------------------------- /slides/snippets/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -e 17 | 18 | export GOOGLE_APPLICATION_CREDENTIALS=../../application_credentials.json 19 | bundle exec rspec 20 | -------------------------------------------------------------------------------- /slides/snippets/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | sudo chown -R `whoami`:admin /usr/local/bin # permission error 17 | if ! type "rvm" > /dev/null 2>&1; then 18 | echo 'Please install RVM:' 19 | echo 'curl -sSL https://get.rvm.io | bash -s stable --ruby' 20 | exit 1 21 | fi 22 | 23 | rvm install ruby-2.3 24 | rvm use 2.3 25 | gem install bundler 26 | 27 | bundle install 28 | -------------------------------------------------------------------------------- /slides/snippets/spec/file_snippets_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | require "spec_helper" 16 | require "file_snippets" 17 | 18 | RSpec.describe FileSnippets do 19 | include TestHelpers 20 | 21 | IMAGE_URL = "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png".freeze 22 | TEMPLATE_PRESENTATION_ID = "1MmTR712m7U_kgeweE57POWwkEyWAV17AVAWjpmltmIg".freeze 23 | DATA_SPREADSHEET_ID = "14KaZMq2aCAGt5acV77zaA_Ps8aDt04G7T0ei4KiXLX8".freeze 24 | CHART_ID = 1107320627 # rubocop:disable Style/NumericLiterals 25 | CUSTOMER_NAME = "Fake Customer".freeze 26 | 27 | before :all do 28 | @snippets = FileSnippets.new(build_drive_service, 29 | build_slides_service, 30 | build_sheets_service) 31 | reset 32 | end 33 | 34 | after :all do 35 | cleanup_files 36 | end 37 | 38 | it "should create a presentation" do 39 | presentation = @snippets.create_presentation "Title" 40 | expect(presentation).to_not be_nil 41 | delete_file_on_cleanup presentation.presentation_id 42 | end 43 | 44 | it "should copy a presentation" do 45 | presentation_id = create_test_presentation 46 | copy_id = @snippets.copy_presentation presentation_id, "My Duplicate Presentation" 47 | expect(copy_id).to_not be_nil 48 | delete_file_on_cleanup copy_id 49 | end 50 | 51 | it "should create a slide" do 52 | presentation_id = create_test_presentation 53 | add_slides presentation_id, 3, "TITLE_AND_TWO_COLUMNS" 54 | page_id = "my_page_id" 55 | response = @snippets.create_slide presentation_id, page_id 56 | expect(response.object_id_prop).to eq(page_id) 57 | delete_file_on_cleanup presentation_id 58 | end 59 | 60 | it "should create a textbox with text" do 61 | presentation_id = create_test_presentation 62 | page_id = add_slides(presentation_id, 1, "BLANK")[0] 63 | response = @snippets.create_textbox_with_text presentation_id, page_id 64 | expect(response.replies.length).to eq(2) 65 | box_id = response.replies[0].create_shape.object_id_prop 66 | expect(box_id).to_not be_nil 67 | end 68 | 69 | it "should create an image" do 70 | presentation_id = create_test_presentation 71 | page_id = add_slides(presentation_id, 1, "BLANK")[0] 72 | response = @snippets.create_image presentation_id, page_id 73 | expect(response.replies.length).to eq(1) 74 | image_id = response.replies[0].create_image.object_id_prop 75 | expect(image_id).to_not be_nil 76 | end 77 | 78 | it "should text merge" do 79 | responses = @snippets.text_merging TEMPLATE_PRESENTATION_ID, DATA_SPREADSHEET_ID 80 | responses.each do |response| 81 | presentation_id = response.presentation_id 82 | expect(presentation_id).to_not be_nil 83 | expect(response.replies.length).to eq(3) 84 | num_replacements = 0 85 | response.replies.each do |reply| 86 | num_replacements += reply.replace_all_text.occurrences_changed 87 | end 88 | expect(num_replacements).to eq(4) 89 | delete_file_on_cleanup presentation_id 90 | end 91 | end 92 | 93 | it "should image merge" do 94 | response = @snippets.image_merging(TEMPLATE_PRESENTATION_ID, 95 | IMAGE_URL, 96 | CUSTOMER_NAME) 97 | presentation_id = response.presentation_id 98 | expect(presentation_id).to_not be_nil 99 | expect(response.replies.length).to eq(2) 100 | num_replacements = 0 101 | response.replies.each do |reply| 102 | num_replacements += reply.replace_all_shapes_with_image.occurrences_changed 103 | end 104 | expect(num_replacements).to eq(2) 105 | delete_file_on_cleanup presentation_id 106 | end 107 | 108 | it "should simple text replace" do 109 | presentation_id = create_test_presentation 110 | page_id = add_slides(presentation_id, 1, "BLANK")[0] 111 | box_id = create_test_textbox presentation_id, page_id 112 | response = @snippets.simple_text_replace presentation_id, box_id, "MY NEW TEXT" 113 | expect(response.replies.length).to eq(2) 114 | end 115 | 116 | it "should text style update" do 117 | presentation_id = create_test_presentation 118 | page_id = add_slides(presentation_id, 1, "BLANK")[0] 119 | box_id = create_test_textbox presentation_id, page_id 120 | response = @snippets.text_style_update presentation_id, box_id 121 | expect(response.replies.length).to eq(3) 122 | end 123 | 124 | it "should create bulleted text" do 125 | presentation_id = create_test_presentation 126 | page_id = add_slides(presentation_id, 1, "BLANK")[0] 127 | box_id = create_test_textbox presentation_id, page_id 128 | response = @snippets.create_bulleted_text presentation_id, box_id 129 | expect(response.replies.length).to eq(1) 130 | end 131 | 132 | it "should create a sheets chart" do 133 | presentation_id = create_test_presentation 134 | page_id = add_slides(presentation_id, 1, "BLANK")[0] 135 | response = @snippets.create_sheets_chart(presentation_id, 136 | page_id, 137 | DATA_SPREADSHEET_ID, 138 | CHART_ID) 139 | expect(response.replies.length).to eq(1) 140 | chart_id = response.replies[0].create_sheets_chart.object_id_prop 141 | expect(chart_id).to_not be_nil 142 | end 143 | 144 | it "should refresh sheets chart" do 145 | presentation_id = create_test_presentation 146 | page_id = add_slides(presentation_id, 1, "BLANK")[0] 147 | chart_id = create_test_sheets_chart(presentation_id, 148 | page_id, 149 | DATA_SPREADSHEET_ID, 150 | CHART_ID) 151 | response = @snippets.refresh_sheets_chart(presentation_id, 152 | chart_id) 153 | expect(response.replies.length).to eq(1) 154 | end 155 | end 156 | -------------------------------------------------------------------------------- /slides/snippets/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | spec_dir = __dir__ 16 | root_dir = File.expand_path File.join(spec_dir, "..") 17 | lib_dir = File.expand_path File.join(root_dir, "lib") 18 | 19 | $LOAD_PATH.unshift spec_dir 20 | $LOAD_PATH.unshift lib_dir 21 | $LOAD_PATH.uniq! 22 | 23 | require "rspec" 24 | require "googleauth" 25 | require "google/apis/slides_v1" 26 | require "google/apis/sheets_v4" 27 | require "google/apis/drive_v3" 28 | 29 | # Test helper 30 | module TestHelpers 31 | def build_drive_service 32 | drive = Google::Apis::DriveV3::DriveService.new 33 | drive.authorization = Google::Auth.get_application_default( 34 | [Google::Apis::DriveV3::AUTH_DRIVE, 35 | Google::Apis::DriveV3::AUTH_DRIVE_APPDATA] 36 | ) 37 | drive 38 | end 39 | 40 | def build_slides_service 41 | slides = Google::Apis::SlidesV1::SlidesService.new 42 | slides.authorization = Google::Auth.get_application_default( 43 | [Google::Apis::SlidesV1::AUTH_PRESENTATIONS, 44 | Google::Apis::SheetsV4::AUTH_SPREADSHEETS] 45 | ) 46 | slides 47 | end 48 | 49 | def build_sheets_service 50 | sheets = Google::Apis::SheetsV4::SheetsService.new 51 | sheets.authorization = Google::Auth.get_application_default( 52 | [Google::Apis::SheetsV4::AUTH_SPREADSHEETS] 53 | ) 54 | sheets 55 | end 56 | 57 | def drive_service 58 | @drive_service ||= build_drive_service 59 | end 60 | 61 | def slides_service 62 | @slides_service ||= build_slides_service 63 | end 64 | 65 | def sheets_service 66 | @sheets_service ||= build_sheets_service 67 | end 68 | 69 | def reset 70 | @files_to_delete = [] 71 | end 72 | 73 | def cleanup_files 74 | @files_to_delete ||= [] 75 | return if @files_to_delete.empty? 76 | 77 | drive_service.batch do 78 | @files_to_delete.each do |file_id| 79 | puts "Deleting file #{file_id}" 80 | drive_service.delete_file file_id do |res, err| 81 | # Ignore errors... 82 | end 83 | end 84 | end 85 | end 86 | 87 | def create_test_presentation 88 | presentation = slides_service.create_presentation( 89 | "title" => "Test Preso" 90 | ) 91 | presentation.presentation_id 92 | end 93 | 94 | def delete_file_on_cleanup file_id 95 | @files_to_delete << file_id 96 | end 97 | 98 | def add_slides presentation_id, num, layout = "TITLE_AND_TWO_COLUMNS" 99 | requests = [] 100 | slide_ids = [] 101 | (0..num).each do |i| 102 | slide_ids << "slide_#{i}" 103 | requests << { 104 | create_slide: { 105 | object_id_prop: slide_ids[i], 106 | slide_layout_reference: { 107 | predefined_layout: layout 108 | } 109 | } 110 | } 111 | end 112 | 113 | req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new requests: requests 114 | slides_service.batch_update_presentation presentation_id, req 115 | slide_ids 116 | end 117 | 118 | def create_test_textbox presentation_id, page_id 119 | box_id = "MyTextBox_01" 120 | pt350 = { 121 | magnitude: 350, 122 | unit: "PT" 123 | } 124 | requests = [] << { 125 | create_shape: { 126 | object_id_prop: box_id, 127 | shape_type: "TEXT_BOX", 128 | element_properties: { 129 | page_object_id: page_id, 130 | size: { 131 | height: pt350, 132 | width: pt350 133 | }, 134 | transform: { 135 | scale_x: 1, 136 | scale_y: 1, 137 | translate_x: 350, 138 | translate_y: 100, 139 | unit: "PT" 140 | } 141 | } 142 | } 143 | } << { 144 | insert_text: { 145 | object_id_prop: box_id, 146 | insertion_index: 0, 147 | text: "New Box Text Inserted" 148 | } 149 | } 150 | 151 | req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new requests: requests 152 | response = slides_service.batch_update_presentation presentation_id, req 153 | response.replies[0].create_shape.object_id_prop 154 | end 155 | 156 | def create_test_sheets_chart presentation_id, page_id, spreadsheet_id, sheet_chart_id 157 | chart_id = "MyChart_01" 158 | emu4m = { 159 | magnitude: 4_000_000, 160 | unit: "EMU" 161 | } 162 | requests = [] << { 163 | create_sheets_chart: { 164 | object_id_prop: chart_id, 165 | spreadsheet_id: spreadsheet_id, 166 | chart_id: sheet_chart_id, 167 | linking_mode: "LINKED", 168 | element_properties: { 169 | page_object_id: page_id, 170 | size: { 171 | height: emu4m, 172 | width: emu4m 173 | }, 174 | transform: { 175 | scale_x: 1, 176 | scale_y: 1, 177 | translate_x: 100_000, 178 | translate_y: 100_000, 179 | unit: "EMU" 180 | } 181 | } 182 | } 183 | } 184 | 185 | req = Google::Apis::SlidesV1::BatchUpdatePresentationRequest.new requests: requests 186 | response = slides_service.batch_update_presentation presentation_id, req 187 | response.replies[0].create_sheets_chart.object_id_prop 188 | end 189 | end 190 | -------------------------------------------------------------------------------- /tasks/quickstart/Gemfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | source "https://rubygems.org" 16 | 17 | gem "google-api-client", "~> 0.28.4" 18 | -------------------------------------------------------------------------------- /tasks/quickstart/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.6.0) 5 | public_suffix (>= 2.0.2, < 4.0) 6 | declarative (0.0.10) 7 | declarative-option (0.1.0) 8 | faraday (0.15.4) 9 | multipart-post (>= 1.2, < 3) 10 | google-api-client (0.28.4) 11 | addressable (~> 2.5, >= 2.5.1) 12 | googleauth (>= 0.5, < 0.10.0) 13 | httpclient (>= 2.8.1, < 3.0) 14 | mime-types (~> 3.0) 15 | representable (~> 3.0) 16 | retriable (>= 2.0, < 4.0) 17 | signet (~> 0.10) 18 | googleauth (0.8.0) 19 | faraday (~> 0.12) 20 | jwt (>= 1.4, < 3.0) 21 | memoist (~> 0.16) 22 | multi_json (~> 1.11) 23 | os (>= 0.9, < 2.0) 24 | signet (~> 0.7) 25 | httpclient (2.8.3) 26 | jwt (2.1.0) 27 | memoist (0.16.0) 28 | mime-types (3.2.2) 29 | mime-types-data (~> 3.2015) 30 | mime-types-data (3.2018.0812) 31 | multi_json (1.13.1) 32 | multipart-post (2.0.0) 33 | os (1.0.0) 34 | public_suffix (3.0.3) 35 | representable (3.0.4) 36 | declarative (< 0.1.0) 37 | declarative-option (< 0.2.0) 38 | uber (< 0.2.0) 39 | retriable (3.1.2) 40 | signet (0.11.0) 41 | addressable (~> 2.3) 42 | faraday (~> 0.9) 43 | jwt (>= 1.5, < 3.0) 44 | multi_json (~> 1.10) 45 | uber (0.1.0) 46 | 47 | PLATFORMS 48 | ruby 49 | 50 | DEPENDENCIES 51 | google-api-client (~> 0.28.4) 52 | 53 | BUNDLED WITH 54 | 1.16.2 55 | -------------------------------------------------------------------------------- /tasks/quickstart/quickstart.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # [START tasks_quickstart] 15 | require "google/apis/tasks_v1" 16 | require "googleauth" 17 | require "googleauth/stores/file_token_store" 18 | require "fileutils" 19 | 20 | OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze 21 | APPLICATION_NAME = "Google Tasks API Ruby Quickstart".freeze 22 | CREDENTIALS_PATH = "credentials.json".freeze 23 | # The file token.yaml stores the user's access and refresh tokens, and is 24 | # created automatically when the authorization flow completes for the first 25 | # time. 26 | TOKEN_PATH = "token.yaml".freeze 27 | SCOPE = Google::Apis::TasksV1::AUTH_TASKS_READONLY 28 | 29 | ## 30 | # Ensure valid credentials, either by restoring from the saved credentials 31 | # files or intitiating an OAuth2 authorization. If authorization is required, 32 | # the user's default browser will be launched to approve the request. 33 | # 34 | # @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials 35 | def authorize 36 | client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH 37 | token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH 38 | authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store 39 | user_id = "default" 40 | credentials = authorizer.get_credentials user_id 41 | if credentials.nil? 42 | url = authorizer.get_authorization_url base_url: OOB_URI 43 | puts "Open the following URL in the browser and enter the " \ 44 | "resulting code after authorization:\n" + url 45 | code = gets 46 | credentials = authorizer.get_and_store_credentials_from_code( 47 | user_id: user_id, code: code, base_url: OOB_URI 48 | ) 49 | end 50 | credentials 51 | end 52 | 53 | # Initialize the API 54 | service = Google::Apis::TasksV1::TasksService.new 55 | service.client_options.application_name = APPLICATION_NAME 56 | service.authorization = authorize 57 | 58 | # Print the first 10 task lists. 59 | response = service.list_tasklists max_results: 10 60 | puts "Task lists:" 61 | puts "No task lists found" if response.items.empty? 62 | response.items.each do |task_list| 63 | puts "#{task_list.title} (#{task_list.id})" 64 | end 65 | # [END tasks_quickstart] 66 | --------------------------------------------------------------------------------