pashto-dictionary/functions/lambda/index.ts

123 lines
3.6 KiB
TypeScript

import { Hono } from "hono";
import { handle } from "hono/aws-lambda";
// wish we could tree shake this!
import { google } from "googleapis";
import { sheets } from "@googleapis/sheets";
import { getEntriesFromSheet } from "../lib/spreadsheet-tools";
import {
checkForErrors,
dictionaryFilename,
dictionaryInfoFilename,
makeDictionaryObject,
makeSitemap,
} from "../lib/publishing-helpers";
import { uploader } from "../lib/uploader";
import { S3Client } from "@aws-sdk/client-s3";
import { getEnv } from "../lib/env-helper";
import { cors } from "hono/cors";
// import { getWordList } from "../lib/word-list-maker";
// import { Types as T } from "@lingdocs/inflect";
// const allWordsJsonFilename = "all-words-dictionary2.json";
const app = new Hono();
app.use(
cors({ origin: ["https://dictionary.lingdocs.com"], credentials: true })
);
app.get("/publish", async (c) => {
// check if caller is authorized as lingdocs admin
// might be nicer to abstract this into some middleware
const cookie = c.req.header("cookie");
if (!cookie) {
c.status(401);
return c.json({
ok: false,
error: "unauthorized",
});
}
const r = await fetch("https://account.lingdocs.com/api/user", {
headers: { Cookie: cookie },
});
const { ok, user } = await r.json();
if (ok !== true || typeof user !== "object" || !user.admin) {
return c.json({
ok: false,
error: "unauthorized",
});
}
const vars = getEnv(c);
const auth = new google.auth.GoogleAuth({
credentials: {
// IMPORTANT!! have to have key stored in Base64 because of the
// weirdness of node handling spaces in the key
private_key: Buffer.from(
vars.LINGDOCS_SERVICE_ACCOUNT_KEY,
"base64"
).toString("ascii"),
client_email: vars.LINGDOCS_SERVICE_ACCOUNT_EMAIL,
},
scopes: [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive.file",
],
});
const { spreadsheets } = sheets({
version: "v4",
auth,
});
const entries = await getEntriesFromSheet({
spreadsheets,
spreadsheetId: vars.LINGDOCS_DICTIONARY_SPREADSHEET,
});
const errors = checkForErrors(entries);
if (errors.length) {
return c.json({
ok: false,
errors,
});
}
const dictionary = makeDictionaryObject(entries);
const sitemap = makeSitemap(dictionary);
// const wordListRes = getWordList(dictionary.entries);
// if (!wordListRes.ok) {
// return c.json({
// ok: false,
// error: "error(s) in creating inflections",
// errors: wordListRes.errors,
// });
// }
// const wordList: T.AllWordsWithInflections = {
// info: dictionary.info,
// words: wordListRes.wordlist,
// };
// got dictionary, now upload it to storage
const s3Client = new S3Client({
region: "auto",
endpoint: vars.DICT_R2_ENDPOINT,
credentials: {
accessKeyId: vars.DICT_R2_KEY_ID,
secretAccessKey: vars.DICT_R2_KEY_SECRET,
},
});
const upload = uploader(vars.DICT_R2_BUCKET, s3Client);
const uploadResult = await Promise.all([
upload(JSON.stringify(dictionary), `${dictionaryFilename}.json`),
upload(JSON.stringify(dictionary.info), `${dictionaryInfoFilename}.json`),
upload(sitemap, `sitemap2.xml`),
// upload(JSON.stringify(wordList), allWordsJsonFilename),
]);
if (uploadResult.some((res) => res.output.$metadata.httpStatusCode !== 200)) {
return c.json({
ok: false,
error: "error uploading file(s)",
uploadResult,
});
}
return c.json({
ok: true,
info: dictionary.info,
});
});
export const handler = handle(app);