|
| 1 | +import * as CF from "cross-fetch" |
| 2 | +import * as E from "fp-ts/lib/Either" |
| 3 | +import * as TE from "fp-ts/lib/TaskEither" |
| 4 | +import { promises as fs } from "fs" |
| 5 | +import { array } from "fp-ts/lib/Array" |
| 6 | +import { pipe } from "fp-ts/lib/pipeable" |
| 7 | +import { TaskEither, taskEither, tryCatch } from "fp-ts/lib/TaskEither" |
| 8 | +import * as R from "rambda" |
| 9 | + |
| 10 | +import { run } from "./under_util" |
| 11 | + |
| 12 | +const makeSpreadsheetUrl = (key: string, gid: string): string => |
| 13 | + `https://docs.google.com/spreadsheets/d/e/${key}/pub?` + |
| 14 | + `gid=${gid}&single=true&output=csv` |
| 15 | + |
| 16 | +const fetchGoogleSpreadSheetCsv = ( |
| 17 | + key: string, |
| 18 | + gid: string |
| 19 | +): TaskEither<Error, string> => { |
| 20 | + const url = makeSpreadsheetUrl(key, gid) |
| 21 | + return tryCatch( |
| 22 | + () => CF.fetch(url).then((x) => x.text()), |
| 23 | + E.toError |
| 24 | + ) |
| 25 | +} |
| 26 | + |
| 27 | +const makeCsvFile = ( |
| 28 | + fn: string, |
| 29 | + key: string, |
| 30 | + gid: string |
| 31 | +): TaskEither<Error, string> => { |
| 32 | + const csv = `${fn}.csv` |
| 33 | + const writeM = (file: string, data: string): TaskEither<Error, void> => |
| 34 | + tryCatch(() => fs.writeFile(csv, data), E.toError) |
| 35 | + |
| 36 | + return pipe( |
| 37 | + fetchGoogleSpreadSheetCsv(key, gid), |
| 38 | + TE.chain(R.partial(writeM, csv)), |
| 39 | + TE.map(_ => csv) |
| 40 | + ) |
| 41 | +} |
| 42 | + |
| 43 | +const makeCsvFile_ = ( |
| 44 | + [fn, key, gid]: [string, string, string] |
| 45 | +): TaskEither<Error, string> => |
| 46 | + makeCsvFile(fn, key, gid) |
| 47 | + |
| 48 | +// eslint-disable-next-line |
| 49 | +// noinspection JSUnusedLocalSymbols |
| 50 | +const cleanSheetName = (sheet: string): string => |
| 51 | + sheet |
| 52 | + .trim() |
| 53 | + .toLowerCase() |
| 54 | + .replace('Foreign-language', '') |
| 55 | + .replace('[/- ]', '_') |
| 56 | + |
| 57 | +// noinspection SpellCheckingInspection |
| 58 | +const key: string = |
| 59 | + '2PACX-1vRd6DGCaxlPwhfgpH_b9jhBHxJ-k-iVXmtOYDVq2w_' + |
| 60 | + 'qJutKk8nKN4iToAqPjtUw7kzh7cZSJuRV8Yra' |
| 61 | + |
| 62 | +// noinspection SpellCheckingInspection |
| 63 | +export const gids: Record<string, string> = { |
| 64 | + 'hotlines': '2133443778', |
| 65 | + //'contents': '151378524', |
| 66 | + 'hokkaido': '2127938906', |
| 67 | + 'tohoku': '1010845727', |
| 68 | + 'kanto': '1686906593', |
| 69 | + 'chubu': '1422675244', |
| 70 | + 'kansai': '843788725', |
| 71 | + 'chugoku': '730111385', |
| 72 | + 'shikoku': '623669625', |
| 73 | + 'kyushu_okinawa': '1647012312', |
| 74 | + 'menu': '151378524', |
| 75 | + 'translations': '340977019', |
| 76 | + 'webpages': '1947687836', |
| 77 | +} |
| 78 | + |
| 79 | +// noinspection JSUnusedGlobalSymbols |
| 80 | +export const areas: Array<string> = |
| 81 | + ['hotlines', 'hokkaido', 'tohoku', 'kanto', 'chubu', 'kansai', 'chugoku', |
| 82 | + 'shikoku', 'kyushu_okinawa', 'all'] |
| 83 | + |
| 84 | +// noinspection JSUnusedGlobalSymbols |
| 85 | +export const sheets: Array<string> = |
| 86 | + Object.keys(gids) |
| 87 | + |
| 88 | +export const makeFn = (sheet: string): string => |
| 89 | + `data/${sheet}` |
| 90 | + |
| 91 | +// noinspection JSUnusedGlobalSymbols |
| 92 | +export const getSheet = (fn: string): string => |
| 93 | + fn.split('/')[3] |
| 94 | + |
| 95 | +// noinspection JSUnusedGlobalSymbols |
| 96 | +export const fns: Array<string> = |
| 97 | + sheets.map(makeFn) |
| 98 | + |
| 99 | +const fnKeyGids: Array<[string, string, string]> = |
| 100 | + Object |
| 101 | + .entries(gids) |
| 102 | + .map(([sheet, gid]) => |
| 103 | + [makeFn(sheet), key, gid] |
| 104 | + ) |
| 105 | + |
| 106 | +const logError = (e: Error): void => |
| 107 | + console.error(e) |
| 108 | + |
| 109 | +// noinspection JSUnusedLocalSymbols |
| 110 | +// eslint-disable-next-line |
| 111 | +const logFile = (file: string): void => |
| 112 | + console.log(`wrote file "${file}"`) |
| 113 | + |
| 114 | +const logFiles = (files: Array<string>): void => { |
| 115 | + const msg = files.map(file => `wrote file "${file}"`).join('\n') |
| 116 | + console.log(msg) |
| 117 | +} |
| 118 | + |
| 119 | +export const makeAllCsvFiles = (): Promise<void> => { |
| 120 | + const makeCsvFiles: TaskEither<Error, Array<string>> = |
| 121 | + array.traverse(taskEither)(fnKeyGids, makeCsvFile_) |
| 122 | + |
| 123 | + return run(makeCsvFiles) |
| 124 | + .then(E.fold(logError, logFiles)) |
| 125 | + .catch(logError) |
| 126 | +} |
| 127 | + |
| 128 | +function main(): void { |
| 129 | + makeAllCsvFiles().then() |
| 130 | +} |
| 131 | + |
| 132 | +if (require.main === module) { |
| 133 | + main() |
| 134 | +} |
0 commit comments