commit cc1486328050f848e83089d1f72a2ea9dc380efc Author: panqihua <1029559041@qq.com> Date: Sat Jan 22 17:43:40 2022 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..02fb9bd --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +token.json +pnpm-lock.yaml +.idea +locale +node_modules +credentials.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..b70a5d1 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# Google Sheets API Quickstart + +Complete the steps described in the [quickstart instructions]( +https://developers.google.com/sheets/api/quickstart/nodejs), and in about five +minutes you'll have a simple Node.js command-line application that makes +requests to the Google Sheets API. + +## Install + +`npm install` + +## Run + +After following the quickstart setup instructions, run the sample: + +`npm start` diff --git a/index.js b/index.js new file mode 100644 index 0000000..5858ad1 --- /dev/null +++ b/index.js @@ -0,0 +1,162 @@ +/** + * @license + * Copyright Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// [START sheets_quickstart] +const fs = require('fs'); +const readline = require('readline'); +const {google} = require('googleapis'); + +// If modifying these scopes, delete token.json. +const SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']; +// The file token.json stores the user's access and refresh tokens, and is +// created automatically when the authorization flow completes for the first +// time. +const TOKEN_PATH = 'token.json'; + +// Load client secrets from a local file. +fs.readFile('credentials.json', (err, content) => { + if (err) return console.log('Error loading client secret file:', err); + // Authorize a client with credentials, then call the Google Sheets API. + authorize(JSON.parse(content), listMajors); +}); + +/** + * Create an OAuth2 client with the given credentials, and then execute the + * given callback function. + * @param {Object} credentials The authorization client credentials. + * @param {function} callback The callback to call with the authorized client. + */ +function authorize(credentials, callback) { + const {client_secret, client_id, redirect_uris} = credentials.installed; + const oAuth2Client = new google.auth.OAuth2( + client_id, client_secret, redirect_uris[0]); + + // Check if we have previously stored a token. + fs.readFile(TOKEN_PATH, (err, token) => { + if (err) return getNewToken(oAuth2Client, callback); + oAuth2Client.setCredentials(JSON.parse(token)); + callback(oAuth2Client); + }); +} + +/** + * Get and store new token after prompting for user authorization, and then + * execute the given callback with the authorized OAuth2 client. + * @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for. + * @param {getEventsCallback} callback The callback for the authorized client. + */ +function getNewToken(oAuth2Client, callback) { + const authUrl = oAuth2Client.generateAuthUrl({ + access_type: 'offline', + scope: SCOPES, + }); + console.log('Authorize this app by visiting this url:', authUrl); + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + rl.question('Enter the code from that page here: ', (code) => { + rl.close(); + oAuth2Client.getToken(code, (err, token) => { + if (err) return console.error('Error while trying to retrieve access token', err); + oAuth2Client.setCredentials(token); + // Store the token to disk for later program executions + fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => { + if (err) return console.error(err); + console.log('Token stored to', TOKEN_PATH); + }); + callback(oAuth2Client); + }); + }); +} + +/** + * Prints the names and majors of students in a sample spreadsheet: + * @see https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit + * @param {google.auth.OAuth2} auth The authenticated Google OAuth client. + */ +function listMajors(auth) { + const sheets = google.sheets({version: 'v4', auth}); + sheets.spreadsheets.values.get({ + spreadsheetId: '1GWnrP4WepYM8ERqSVGwKw5yxezMLnpdjxT0usn5mQKU', + range: 'i18n', + }, (err, res) => { + if (err) return console.log('The API returned an error: ' + err); + const rows = res.data.values; + + // console.info(rows) + let keyIndex=rows[0].indexOf('key') + if (rows.length&&keyIndex!==-1&&rows[0][keyIndex+1]==='default') { + + let keys=rows.slice(1).map((item,row)=>{return {row:row+1,key:item[keyIndex]}}) + + let i18n= rows[0].slice(keyIndex+1).map(()=>{return {}}) + console.info(`共找到${i18n.length-1}种语言,${keys.length}个词条`) + keys.map((key,row)=>{ + i18n.map((obj,column)=>{ + + if(!/^[a-zA-Z][0-9a-zA-Z_]+$/g.test(key.key)){ + console.error(`第${row+1}行${key.key}不合法,key必须以英文字母开头,只能包含字母数字和下划线`) + return + } + + if(key.key in obj){ + console.warn(`第${row+1}行${key.key}已经在第${rows[key.row]}行定义了!`) + } + let value=rows[row+1][column+keyIndex+1]||'' + if(value===''){ + console.warn(`第${row+1}行${key.key}对应的${rows[0].slice(keyIndex+1)[column]}没有翻译!`) + } + obj[key.key]=value + }) + }) + + console.info(i18n) + let dir='locale' + if (!fs.existsSync(dir)){ + fs.mkdir(dir,function(error){ + if(error){ + console.log(error); + return false; + } + createFile(rows[0].slice(keyIndex+1),i18n) + }) + }else{ + createFile(rows[0].slice(keyIndex+1),i18n) + } + + + } else { + console.log('语言包没有翻译文本或格式不合法'); + } + }); +} + +function createFile(languages,i18n){ + languages.map((filename,index)=>{ + fs.writeFile(`locale/${filename}.json`, JSON.stringify(i18n[index]), (err) => { + if (err) { + throw err; + } + }); + }) +} +// [END sheets_quickstart] + +module.exports = { + SCOPES, + listMajors, +}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..0cc0589 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,261 @@ +{ + "name": "google-sheets-nodejs-quickstart", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "5.0.1" + } + }, + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "requires": { + "es6-promisify": "5.0.0" + } + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "bignumber.js": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", + "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "2.1.1" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "es6-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", + "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "4.2.6" + } + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "fast-text-encoding": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.0.tgz", + "integrity": "sha512-R9bHCvweUxxwkDwhjav5vxpFvdPGlVngtqmx4pIZfSUhM/Q4NiIUHB456BAf+Q1Nwu3HEZYONtu+Rya+af4jiQ==" + }, + "gaxios": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-1.8.4.tgz", + "integrity": "sha512-BoENMnu1Gav18HcpV9IleMPZ9exM+AvUjrAOV4Mzs/vfz2Lu/ABv451iEXByKiMPn2M140uul1txXCg83sAENw==", + "requires": { + "abort-controller": "3.0.0", + "extend": "3.0.2", + "https-proxy-agent": "2.2.1", + "node-fetch": "2.5.0" + } + }, + "gcp-metadata": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-1.0.0.tgz", + "integrity": "sha512-Q6HrgfrCQeEircnNP3rCcEgiDv7eF9+1B+1MMgpE190+/+0mjQR8PxeOaRgxZWmdDAF9EIryHB9g1moPiw1SbQ==", + "requires": { + "gaxios": "1.8.4", + "json-bigint": "0.3.0" + } + }, + "google-auth-library": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-3.1.2.tgz", + "integrity": "sha512-cDQMzTotwyWMrg5jRO7q0A4TL/3GWBgO7I7q5xGKNiiFf9SmGY/OJ1YsLMgI2MVHHsEGyrqYnbnmV1AE+Z6DnQ==", + "requires": { + "base64-js": "1.3.0", + "fast-text-encoding": "1.0.0", + "gaxios": "1.8.4", + "gcp-metadata": "1.0.0", + "gtoken": "2.3.3", + "https-proxy-agent": "2.2.1", + "jws": "3.2.2", + "lru-cache": "5.1.1", + "semver": "5.7.0" + } + }, + "google-p12-pem": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-1.0.4.tgz", + "integrity": "sha512-SwLAUJqUfTB2iS+wFfSS/G9p7bt4eWcc2LyfvmUXe7cWp6p3mpxDo6LLI29MXdU6wvPcQ/up298X7GMC5ylAlA==", + "requires": { + "node-forge": "0.8.2", + "pify": "4.0.1" + } + }, + "googleapis": { + "version": "39.2.0", + "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-39.2.0.tgz", + "integrity": "sha512-66X8TG1B33zAt177sG1CoKoYHPP/B66tEpnnSANGCqotMuY5gqSQO8G/0gqHZR2jRgc5CHSSNOJCnpI0SuDxMQ==", + "requires": { + "google-auth-library": "3.1.2", + "googleapis-common": "0.7.2" + } + }, + "googleapis-common": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-0.7.2.tgz", + "integrity": "sha512-9DEJIiO4nS7nw0VE1YVkEfXEj8x8MxsuB+yZIpOBULFSN9OIKcUU8UuKgSZFU4lJmRioMfngktrbkMwWJcUhQg==", + "requires": { + "gaxios": "1.8.4", + "google-auth-library": "3.1.2", + "pify": "4.0.1", + "qs": "6.7.0", + "url-template": "2.0.8", + "uuid": "3.3.2" + } + }, + "gtoken": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-2.3.3.tgz", + "integrity": "sha512-EaB49bu/TCoNeQjhCYKI/CurooBKkGxIqFHsWABW0b25fobBYVTMe84A8EBVVZhl8emiUdNypil9huMOTmyAnw==", + "requires": { + "gaxios": "1.8.4", + "google-p12-pem": "1.0.4", + "jws": "3.2.2", + "mime": "2.4.2", + "pify": "4.0.1" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "requires": { + "agent-base": "4.2.1", + "debug": "3.2.6" + } + }, + "json-bigint": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.0.tgz", + "integrity": "sha1-DM2RLEuCcNBfBW+9E4FLU9OCWx4=", + "requires": { + "bignumber.js": "7.2.1" + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "5.1.2" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "1.4.1", + "safe-buffer": "5.1.2" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "3.0.3" + } + }, + "mime": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz", + "integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg==" + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node-fetch": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.5.0.tgz", + "integrity": "sha512-YuZKluhWGJwCcUu4RlZstdAxr8bFfOVHakc1mplwHkk8J+tqM1Y5yraYvIUpeX8aY7+crCwiELJq7Vl0o0LWXw==" + }, + "node-forge": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.8.2.tgz", + "integrity": "sha512-mXQ9GBq1N3uDCyV1pdSzgIguwgtVpM7f5/5J4ipz12PKWElmPpVWLDuWl8iXmhysr21+WmX/OJ5UKx82wjomgg==" + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + }, + "url-template": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", + "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c1ab7d9 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "google-sheets-nodejs-quickstart", + "version": "1.0.0", + "description": "A simple Node.js command-line application that makes requests to the Google Sheets API.", + "private": true, + "dependencies": { + "googleapis": "^39.0.0" + }, + "devDependencies": {}, + "engines": { + "node": ">=6.4.0" + }, + "scripts": { + "start": "node ." + }, + "license": "Apache-2.0" +}