sheets/lib.ts
2026-01-05 02:17:29 +02:00

108 lines
2.6 KiB
TypeScript

export const thIgnore = [
"🎹Worst Comps & Edits",
"🎹 Yedits",
"🎹 Comps & Edits",
"Comps & Edits",
"Worst Comps & Edits",
"Yedits",
"AI Models",
"🎹 BPM & Key Tracker",
"🎹Comps & Edits",
"🎹 Worst Comps & Edits",
"Allegations",
"Rap Disses Timeline",
"Underground Artists",
"bpmkeytracker",
]
export function jsonToCsv(data: unknown | unknown[]) {
const arr = Array.isArray(data) ? data : [data];
const headers = [...new Set(arr.flatMap((o) => Object.keys(o)))];
const escape = (v: string) => `"${String(v ?? "").replace(/"/g, '""')}"`;
const rows = arr.map((o) => headers.map((h) => escape(o[h])).join(","));
return [headers.join(","), ...rows].join("\n");
}
export enum TripleBool {
MOSTLY = 2,
YES = 1,
NO = 0,
}
export interface Entry {
name: string;
url: string;
credit: string;
updated: TripleBool;
links_work: TripleBool;
best: boolean;
}
export type Change =
| { op: "delete"; name: string }
| { op: "create"; name: string; item: Entry }
| { op: "update"; name: string; changes: Partial<Entry> };
const TripleBoolStrings: Record<TripleBool, string> = {
[TripleBool.MOSTLY]: "Mostly",
[TripleBool.YES]: "Yes",
[TripleBool.NO]: "No",
};
export function tripleBoolToString(v: TripleBool): string {
return TripleBoolStrings[v];
}
export function tripleBool(bool: string): TripleBool {
if (bool.toLowerCase() == "mostly") {
return TripleBool.MOSTLY;
} else if (bool.toLowerCase() == "yes") {
return TripleBool.YES;
} else if (bool.toLowerCase() == "no") {
return TripleBool.NO;
}
console.error(
"tripleBool conversion function errored, mysteriously! Passed in: " + bool,
);
return TripleBool.NO;
}
export function prettyStringify(z: unknown) {
return JSON.stringify(z, null, 2)
.replace(/\n {2}"/g, ' "')
.replace(/\n}/, " }");
}
export function requireBasicAuth(req: Request): Response | null {
const auth = req.headers.get("authorization");
if (!auth || !auth.startsWith("Basic ")) {
return new Response("Auth required", {
status: 401,
headers: { "WWW-Authenticate": 'Basic realm="acx-sheets"' },
});
}
const decoded = Buffer.from(auth.slice(6), "base64").toString("utf8");
const [user, pass] = decoded.split(":");
if (user !== process.env.MERGE_USER || pass !== process.env.MERGE_PASS) {
return new Response("Forbidden", { status: 403 });
}
return null;
}
export function ndjsonToJson(ndjson: string): unknown[] {
return ndjson
.split("\n")
.map((z) => {
try {
return JSON.parse(z);
} catch {
return undefined;
}
})
.filter(Boolean);
}