-
Notifications
You must be signed in to change notification settings - Fork 2
/
googleapis-client.js
125 lines (106 loc) · 3.44 KB
/
googleapis-client.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
const { google } = require('googleapis')
// const { auth, JWT } = require('google-auth-library')
const util = require('util')
async function getSheets({ credentials, spreadsheetId, sheetsNames = [] }) {
// const keys = require('./auth.json');
// const client = new JWT({
// email: keys.client_email,
// key: keys.private_key,
// scopes: ['https://www.googleapis.com/auth/spreadsheets.readonly'],
// });
const auth = new google.auth.GoogleAuth({
// keyFile: "auth.json", // TODO add possibility to use key file for auth
// credentials: { // This works
// client_email: keys.client_email,
// private_key: keys.private_key
// },
credentials,
scopes: ['https://www.googleapis.com/auth/spreadsheets.readonly']
});
const googleSheetsApiV4 = google.sheets('v4')
const sheetsApiClient = util.promisify(googleSheetsApiV4.spreadsheets.get.bind(googleSheetsApiV4))
let ranges
if (sheetsNames.length > 0) {
ranges = (await getAllSheetsRanges(sheetsApiClient, auth, spreadsheetId))
.filter(({title}) => sheetsNames.includes(title))
.map(({range}) => range)
}
return await getSheetsData(sheetsApiClient, auth, spreadsheetId, ranges)
}
// TODO: Used for local development and testing
// getSheets({
// spreadsheetId: '1oFig-VwfFKP3BLsW4ZgLiw5ftAfcD4jpcUwmXBdhCPU',
// sheets: ['corrupted_sheet']
// }).catch(console.error);
async function getSheetsData(sheetsApiClient, auth, spreadsheetId, ranges) {
const result = await sheetsApiClient({
auth,
spreadsheetId,
includeGridData: true,
ranges,
alt: 'json',
prettyPrint: true,
fields: 'sheets.properties.title,sheets.data.rowData.values.formattedValue'
})
return result.data.sheets
.filter(sheet => Object.keys(sheet.data[0]).length)
.map(sheet => {
const { header, rows } = splitRowDataIntoHeaderAndRows(sheet.data[0].rowData)
return {
title: sheet.properties.title,
header,
rows
}
})
}
function convertSheetRowToArray(row) {
return row.values.map(({ formattedValue }) => formattedValue)
}
function splitRowDataIntoHeaderAndRows(rowData) {
const rowHasCells = row => Object.keys(row).length > 0
const rowHasKeyCell = row => Object.keys(row.values[0]).length > 0
let [header, ...rows] = rowData
if (!rowHasKeyCell(rowData[0])) {
header.values[0] = { formattedValue: 'key' }
}
return {
header: convertSheetRowToArray(header),
rows: rows
.filter(rowHasCells)
.filter(rowHasKeyCell)
.map(convertSheetRowToArray)
}
}
async function getAllSheetsRanges(sheetsApiClient, auth, spreadsheetId) {
const result = await sheetsApiClient({
auth,
spreadsheetId,
includeGridData: false,
alt: 'json',
prettyPrint: true,
fields: 'sheets.properties.title,sheets.properties.gridProperties'
})
return result.data.sheets.map((sheet) => ({
title: sheet.properties.title,
rowCount: sheet.properties.gridProperties.rowCount,
columnCount: sheet.properties.gridProperties.columnCount
}))
.map(sheet => ({
...sheet,
range: `${sheet.title}!A1:${columnToLetter(sheet.columnCount)}${sheet.rowCount}`
}))
}
function columnToLetter(column) {
let temp;
let letter = '';
let col = column;
while (col > 0) {
temp = (col - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
col = (col - temp - 1) / 26;
}
return letter;
}
module.exports = {
getSheets
}