-
Notifications
You must be signed in to change notification settings - Fork 3.8k
/
index.js
134 lines (120 loc) · 5.09 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
* Copyright 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
// Sample trigger function that copies new Firebase data to a Google Sheet
const functions = require('firebase-functions/v1');
const admin = require('firebase-admin');
admin.initializeApp();
const {OAuth2Client} = require('google-auth-library');
const {google} = require('googleapis');
// TODO: Use firebase functions:config:set to configure your googleapi object:
// googleapi.client_id = Google API client ID,
// googleapi.client_secret = client secret, and
// googleapi.sheet_id = Google Sheet id (long string in middle of sheet URL)
const CONFIG_CLIENT_ID = functions.config().googleapi.client_id;
const CONFIG_CLIENT_SECRET = functions.config().googleapi.client_secret;
const CONFIG_SHEET_ID = functions.config().googleapi.sheet_id;
// TODO: Use firebase functions:config:set to configure your watchedpaths object:
// watchedpaths.data_path = Firebase path for data to be synced to Google Sheet
const CONFIG_DATA_PATH = functions.config().watchedpaths.data_path;
// The OAuth Callback Redirect.
const FUNCTIONS_REDIRECT = `https://${process.env.GCLOUD_PROJECT}.firebaseapp.com/oauthcallback`;
// setup for authGoogleAPI
const SCOPES = ['https://www.googleapis.com/auth/spreadsheets'];
const functionsOauthClient = new OAuth2Client(CONFIG_CLIENT_ID, CONFIG_CLIENT_SECRET,
FUNCTIONS_REDIRECT);
// OAuth token cached locally.
let oauthTokens = null;
// visit the URL for this Function to request tokens
exports.authgoogleapi = functions.https.onRequest((req, res) => {
res.set('Cache-Control', 'private, max-age=0, s-maxage=0');
res.redirect(functionsOauthClient.generateAuthUrl({
access_type: 'offline',
scope: SCOPES,
prompt: 'consent',
}));
});
// setup for OauthCallback
const DB_TOKEN_PATH = '/api_tokens';
// after you grant access, you will be redirected to the URL for this Function
// this Function stores the tokens to your Firebase database
exports.oauthcallback = functions.https.onRequest(async (req, res) => {
res.set('Cache-Control', 'private, max-age=0, s-maxage=0');
const code = `${req.query.code}`;
try {
const { tokens } = await functionsOauthClient.getToken(code);
// Now tokens contains an access_token and an optional refresh_token. Save them.
await admin.database().ref(DB_TOKEN_PATH).set(tokens);
res.status(200).send('App successfully configured with new Credentials. '
+ 'You can now close this page.');
} catch (error) {
res.status(400).send(error);
}
});
// trigger function to write to Sheet when new data comes in on CONFIG_DATA_PATH
exports.appendrecordtospreadsheet = functions.database.ref(`${CONFIG_DATA_PATH}/{ITEM}`).onCreate(
(snap) => {
const newRecord = snap.val();
return appendPromise({
spreadsheetId: CONFIG_SHEET_ID,
range: 'A:C',
valueInputOption: 'USER_ENTERED',
insertDataOption: 'INSERT_ROWS',
resource: {
values: [[newRecord.firstColumn, newRecord.secondColumn, newRecord.thirdColumn]],
},
});
});
// accepts an append request, returns a Promise to append it, enriching it with auth
function appendPromise(requestWithoutAuth) {
return new Promise((resolve, reject) => {
return getAuthorizedClient().then((client) => {
const sheets = google.sheets('v4');
const request = requestWithoutAuth;
request.auth = client;
return sheets.spreadsheets.values.append(request, (err, response) => {
if (err) {
functions.logger.log(`The API returned an error: ${err}`);
return reject(err);
}
return resolve(response.data);
});
});
});
}
// checks if oauthTokens have been loaded into memory, and if not, retrieves them
async function getAuthorizedClient() {
if (oauthTokens) {
return functionsOauthClient;
}
const snapshot = await admin.database().ref(DB_TOKEN_PATH).once('value');
oauthTokens = snapshot.val();
functionsOauthClient.setCredentials(oauthTokens);
return functionsOauthClient;
}
// HTTPS function to write new data to CONFIG_DATA_PATH, for testing
exports.testsheetwrite = functions.https.onRequest(async (req, res) => {
const random1 = Math.floor(Math.random() * 100);
const random2 = Math.floor(Math.random() * 100);
const random3 = Math.floor(Math.random() * 100);
const ID = new Date().getUTCMilliseconds();
await admin.database().ref(`${CONFIG_DATA_PATH}/${ID}`).set({
firstColumn: random1,
secondColumn: random2,
thirdColumn: random3,
});
res.send(`Wrote ${random1}, ${random2}, ${random3} to DB, trigger should now update Sheet.`);
});