わざわざ管理画面を作るのめんどいからGoogleSheetsで済ませたい、というのは稀に良くある状況だと思います。
みたいなスプレッドシートで管理されたデータが欲しかったとして
Google Sheets APIを利用すればCloud Functionsに限らずどこからでも何からでもアクセスは出来るんですが、Cloud Functions等の場合はデフォルトのサービスアカウントを利用する事でちょっと楽をできます。
"dependencies": {
...,
"googleapis": "^39.2.0",
}
import * as gapis from 'googleapis';
export class GoogleSpreadSheets {
private auth = async (): Promise<gapis.sheets_v4.Sheets> => {
const client = await gapis.google.auth.getClient({
scopes: ['https://www.googleapis.com/auth/spreadsheets.readonly']
});
return new gapis.sheets_v4.Sheets({ auth: client });
}
fetchValueRange = async (spreadsheetId: string, tabTitle: string): Promise<gapis.sheets_v4.Schema$ValueRange> => {
const authed = await this.auth();
const res = await authed.spreadsheets.values.get({ spreadsheetId: spreadsheetId, range: tabTitle });
return res.data;
}
}
spreadsheetIdというのはシートのURLにおける
https://docs.google.com/spreadsheets/d/${spreadsheetId}/
の部分で、rangeには今回の場合はタブ名を指定してますがA1:B1とかそういう書式が使えます。余談ですがGoogle Sheets APIを使っていると、Sheetsとは何かSheetとは何かみたいな迷宮へいざなわれます。
で、APIから返ってくるValueRangeを
import * as entity from '../Entity';
export class GoogleSheetData {
private sheet: google.sheets_v4.Schema$ValueRange;
private rows: any[];
constructor(sheet: google.sheets_v4.Schema$ValueRange) {
this.sheet = sheet;
// 先頭行を飛ばしてる
this.rows = this.rowRange().slice(1).map(this.rowValuesAt);
}
toDogs = (): entity.Dog[] => {
return this.rows.map(this.toDog).filter(utils.valueIsExist);
}
private toDog = (row: any[]): entity.Dog | undefined => {
const data: entity.DogData = {
name: row[0],
race: row[1],
};
if (!entity.dataIsDogData(data)) {
console.error('GoogleSheetData.toDog %O is not DogData', data);
return undefined;
}
return new entity.Dog(data);
}
private rowValuesAt = (i: number): any[] => {
if (this.sheet.values === undefined) {
return [];
}
return this.sheet.values[i];
}
private rowCount = (): number => {
if (this.sheet.values === undefined) {
return 0;
}
return this.sheet.values.length;
}
private rowRange = (): number[] => {
return this.range(this.rowCount());
}
private range = (l: number): number[] => {
return Array.from({ length: l }, (v, i) => i);
};
とか何とかしてやるとシートから大量の犬を生成するコードが出来ます。でデプロイした後、最後にこのfunctionのサービスアカウントに目的のシートへのアクセス権をつけてやる必要があります。
から目的のfunctionの詳細を表示すれば利用している「サービスアカウント」の名前がわかる(Cloud Functions for Firebaseの場合も実体はCloud Functionsなので同様)ので、目的のシートを開いて右上にある共有ボタンから
さっき確認したサービスアカウント名を入力して招待すれば該当シートへのアクセス権が付与されます。
また権限以前にGoogle Sheets API自体を
https://console.cloud.google.com/apis/library
から有効状態にしておく必要もあります。
留意点としてGoogle Sheets APIはそこそこレスポンスが遅いので、それが問題になるようであれば1日1回とかFireStoreにでも犬達を突っ込んでおけば良いと思います。