get rid of sheets frontend, use typescript, use ndjson
Some checks failed
Sheets Deploy Hook / notify (push) Has been cancelled
Some checks failed
Sheets Deploy Hook / notify (push) Has been cancelled
This commit is contained in:
parent
3fcc874852
commit
f5973ba5a0
59 changed files with 757 additions and 7830 deletions
118
index.ts
Normal file
118
index.ts
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
import {parseHTML} from "linkedom"
|
||||
import { ndjsonToJson, tripleBool, tripleBoolToString } from "./lib";
|
||||
import * as fs from "fs/promises"
|
||||
import { existsSync } from "fs";
|
||||
|
||||
const tracker_page = "https://docs.google.com/spreadsheets/u/0/d/1Z8aANbxXbnUGoZPRvJfWL3gz6jrzPPrwVt3d0c1iJ_4/htmlview/sheet?headers=false&gid=1884837542"
|
||||
|
||||
async function getTH() {
|
||||
const req = await fetch(tracker_page);
|
||||
const txt = await req.text()
|
||||
|
||||
const { document } = parseHTML(txt);
|
||||
|
||||
const table_body = document.querySelector(".waffle > tbody");
|
||||
if(!table_body) throw new Error("Missing table body..")
|
||||
|
||||
//@ts-expect-error .children can be spread-operator'd
|
||||
const rows = [...table_body.children]
|
||||
|
||||
let ndjson = "";
|
||||
|
||||
for (let i = 4; i < rows.length; i++) {
|
||||
if(!rows[i].children[1]) {
|
||||
break;
|
||||
}
|
||||
let trackerName = rows[i].children[1].innerText;
|
||||
if (!trackerName) continue;
|
||||
const urlElement = rows[i].children[1].querySelector("a");
|
||||
if (!urlElement) continue;
|
||||
|
||||
const trackerUrl = new URL(urlElement.href).searchParams.get("q");
|
||||
|
||||
const credits = rows[i].children[2].innerText;
|
||||
const updated = tripleBool(rows[i].children[3].innerText);
|
||||
const links_work = tripleBool(rows[i].children[4].innerText);
|
||||
|
||||
const best = trackerName.startsWith("⭐");
|
||||
|
||||
trackerName = trackerName
|
||||
.replace(/([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g, '')
|
||||
.trim();
|
||||
ndjson += JSON.stringify({ name: trackerName, url: trackerUrl, credits, updated, links_work, best }) + "\n";
|
||||
}
|
||||
|
||||
return ndjson;
|
||||
}
|
||||
|
||||
async function runComparison() {
|
||||
console.log("Comparing..")
|
||||
const data = await getTH();
|
||||
const old = (await fs.readFile("./th_artists.ndjson")).toString("utf8");
|
||||
|
||||
if(Bun.hash(old) !== Bun.hash(data)) {
|
||||
const oldJson = ndjsonToJson(old);
|
||||
const newJson = ndjsonToJson(data);
|
||||
|
||||
const oldMap = Object.fromEntries(oldJson.map(item => [item.name, item]));
|
||||
const newMap = Object.fromEntries(newJson.map(item => [item.name, item]));
|
||||
|
||||
let message = "## TH Change Detection\n\n";
|
||||
|
||||
for (const name in oldMap) {
|
||||
const oldItem = oldMap[name];
|
||||
const newItem = newMap[name];
|
||||
if (!newItem) {
|
||||
message += `**DELETED**: \`${name}\`\n`;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (oldItem.url !== newItem.url) message += `**CHANGED URL** for \`${name}\`\n`;
|
||||
if (oldItem.credits !== newItem.credits) message += `**CHANGED CREDITS** for \`${name}\`\n`;
|
||||
if (oldItem.links_work !== newItem.links_work) message += `**CHANGED WORKING LINKS STATUS** for \`${name}\`, from ${tripleBoolToString(oldItem.links_work)} to ${tripleBoolToString(newItem.links_work)}\n`;
|
||||
if (oldItem.updated !== newItem.updated) message += `**CHANGED UPDATED** for \`${name}\`, from ${tripleBoolToString(oldItem.updated)} to ${tripleBoolToString(newItem.updated)}\n`;
|
||||
if (oldItem.best !== newItem.best) message += `**CHANGED BEST STATUS** for \`${name}\`, from ${oldItem.best ? "Yes" : "No"} to ${newItem.best ? "Yes" : "No"}\n`;
|
||||
}
|
||||
|
||||
for (const name in newMap) {
|
||||
if (!oldMap[name]) {
|
||||
message += `**NEW**: \`${name}\`\n`;
|
||||
}
|
||||
}
|
||||
|
||||
if (message.trim() !== "## Change Detection") {
|
||||
await fetch(process.env.WEBHOOK_URL!, {
|
||||
method: 'POST',
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ content: message })
|
||||
});
|
||||
}
|
||||
|
||||
await fs.writeFile("./th_artists.ndjson", data);
|
||||
}
|
||||
}
|
||||
|
||||
if (!existsSync("./th_artists.ndjson")) {
|
||||
console.log("Assuming first run. Downloading TH info and waiting 50s.")
|
||||
await fs.writeFile("./th_artists.ndjson", await getTH());
|
||||
} else {
|
||||
await runComparison();
|
||||
}
|
||||
|
||||
setInterval(async () => {
|
||||
await runComparison();
|
||||
}, 50000)
|
||||
|
||||
Bun.serve({
|
||||
routes: {
|
||||
"/": () => new Response("Sheets v2"),
|
||||
"/artists.ndjson": async () => new Response(await fs.readFile("artists.ndjson")),
|
||||
"/th_artists.ndjson": async () => new Response(await fs.readFile("th_artists.ndjson")),
|
||||
},
|
||||
fetch() {
|
||||
return new Response("Unmatched route");
|
||||
},
|
||||
|
||||
hostname: "0.0.0.0",
|
||||
port: 5000
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue