108 lines
2.6 KiB
TypeScript
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);
|
|
}
|