hs2-last-updated: woohoo! num updates
This commit is contained in:
parent
14f902c1d7
commit
1ae519267e
1 changed files with 70 additions and 25 deletions
|
@ -4,9 +4,12 @@
|
||||||
// okay aaaa hs2 will end that will be sad and good i guess but
|
// okay aaaa hs2 will end that will be sad and good i guess but
|
||||||
// not important right now
|
// not important right now
|
||||||
|
|
||||||
|
// would be neat (but painful) to have it actually roll like an analog thing
|
||||||
|
|
||||||
import { contentType } from "https://deno.land/std@0.202.0/media_types/mod.ts";
|
import { contentType } from "https://deno.land/std@0.202.0/media_types/mod.ts";
|
||||||
import {
|
import {
|
||||||
DOMParser,
|
DOMParser,
|
||||||
|
NodeList,
|
||||||
NodeType,
|
NodeType,
|
||||||
} from "https://deno.land/x/deno_dom@v0.1.38/deno-dom-wasm.ts";
|
} from "https://deno.land/x/deno_dom@v0.1.38/deno-dom-wasm.ts";
|
||||||
import {
|
import {
|
||||||
|
@ -17,7 +20,32 @@ import {
|
||||||
// not sure how worthwhile this optimization is but
|
// not sure how worthwhile this optimization is but
|
||||||
const dom_parser = new DOMParser();
|
const dom_parser = new DOMParser();
|
||||||
|
|
||||||
async function get_last_update_date(): Promise<Date | string> {
|
const murica_short_date = new Intl.DateTimeFormat("en-US", {
|
||||||
|
month: "numeric",
|
||||||
|
day: "numeric",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
|
||||||
|
function get_updates_for_date(
|
||||||
|
{ date, ps }: { date: Date; ps: NodeList },
|
||||||
|
): number {
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
const looking_for = murica_short_date.format(date) + " - ";
|
||||||
|
|
||||||
|
ps.forEach((p) => {
|
||||||
|
if (
|
||||||
|
p.childNodes[0] && p.childNodes[0].nodeType == NodeType.TEXT_NODE &&
|
||||||
|
p.childNodes[0].textContent == looking_for
|
||||||
|
) count++;
|
||||||
|
});
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function get_last_update_date(): Promise<
|
||||||
|
{ last_updated: Date; last_update_count: number } | string
|
||||||
|
> {
|
||||||
try {
|
try {
|
||||||
const res = await fetch("https://homestuck2.com/log");
|
const res = await fetch("https://homestuck2.com/log");
|
||||||
const body = await res.text();
|
const body = await res.text();
|
||||||
|
@ -27,11 +55,13 @@ async function get_last_update_date(): Promise<Date | string> {
|
||||||
const doc = dom_parser.parseFromString(body, "text/html");
|
const doc = dom_parser.parseFromString(body, "text/html");
|
||||||
if (!doc) return "couldn't parse the body into the DOM";
|
if (!doc) return "couldn't parse the body into the DOM";
|
||||||
|
|
||||||
const p = doc.querySelector("p");
|
const ps = doc.querySelectorAll("p");
|
||||||
if (!p) return "couldn't get a p from the doc";
|
if (!ps) return "couldn't get the ps from the doc";
|
||||||
|
|
||||||
|
if (!ps[0]) return "couldn't get even a single p from the doc (bad!)";
|
||||||
|
|
||||||
// should really enable strict indexing
|
// should really enable strict indexing
|
||||||
const us_date_node = p.childNodes[0];
|
const us_date_node = ps[0].childNodes[0];
|
||||||
if (!us_date_node || us_date_node.nodeType != NodeType.TEXT_NODE) {
|
if (!us_date_node || us_date_node.nodeType != NodeType.TEXT_NODE) {
|
||||||
return "couldn't get a date node from the log entry";
|
return "couldn't get a date node from the log entry";
|
||||||
}
|
}
|
||||||
|
@ -42,7 +72,10 @@ async function get_last_update_date(): Promise<Date | string> {
|
||||||
if (Number.isNaN(date.valueOf())) {
|
if (Number.isNaN(date.valueOf())) {
|
||||||
return `got an invalid date :(. the text_content was '${us_date}'`;
|
return `got an invalid date :(. the text_content was '${us_date}'`;
|
||||||
}
|
}
|
||||||
return date;
|
return {
|
||||||
|
last_updated: date,
|
||||||
|
last_update_count: get_updates_for_date({ date, ps }),
|
||||||
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return `caught error: ${e}`;
|
return `caught error: ${e}`;
|
||||||
}
|
}
|
||||||
|
@ -51,9 +84,9 @@ async function get_last_update_date(): Promise<Date | string> {
|
||||||
async function check_again() {
|
async function check_again() {
|
||||||
last_checked = new Date();
|
last_checked = new Date();
|
||||||
|
|
||||||
const new_date = await get_last_update_date();
|
const stuff = await get_last_update_date();
|
||||||
if (typeof new_date == "string") {
|
if (typeof stuff == "string") {
|
||||||
console.log(`failed to get a date when checking 😬: '${new_date}'`);
|
console.log(`failed to get a date when checking 😬: '${stuff}'`);
|
||||||
console.log(
|
console.log(
|
||||||
"^ ironically enough, this is more likely when there *is* an update",
|
"^ ironically enough, this is more likely when there *is* an update",
|
||||||
);
|
);
|
||||||
|
@ -62,7 +95,8 @@ async function check_again() {
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
last_updated = new_date;
|
last_updated = stuff.last_updated;
|
||||||
|
last_update_count = stuff.last_update_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
function days_since_update(): number {
|
function days_since_update(): number {
|
||||||
|
@ -73,6 +107,7 @@ function days_since_update(): number {
|
||||||
// silly, i know
|
// silly, i know
|
||||||
let last_updated: Date = new Date(0);
|
let last_updated: Date = new Date(0);
|
||||||
let last_checked: Date = new Date();
|
let last_checked: Date = new Date();
|
||||||
|
let last_update_count = 0;
|
||||||
await check_again();
|
await check_again();
|
||||||
|
|
||||||
// *definitely* a worthwhile optimization
|
// *definitely* a worthwhile optimization
|
||||||
|
@ -81,9 +116,8 @@ const font = await fetch("https://static.pyrope.net/courier-std-bold.otf")
|
||||||
.then((r) => r.arrayBuffer())
|
.then((r) => r.arrayBuffer())
|
||||||
.then((b) => new Uint8Array(b));
|
.then((b) => new Uint8Array(b));
|
||||||
|
|
||||||
function make_image(): Image {
|
function make_image(n: number): Image {
|
||||||
const days = Math.floor(days_since_update()).toString().padStart(3, "0");
|
const days = Math.floor(n).toString().padStart(3, "0");
|
||||||
console.log(days_since_update());
|
|
||||||
const image = new Image(106, 44);
|
const image = new Image(106, 44);
|
||||||
const text = Image.renderText(
|
const text = Image.renderText(
|
||||||
font,
|
font,
|
||||||
|
@ -96,22 +130,33 @@ function make_image(): Image {
|
||||||
return image.composite(text, -5);
|
return image.composite(text, -5);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function update_image() {
|
async function update_images() {
|
||||||
image = await make_image().encode();
|
[last_updated_image, last_update_count_image] = await Promise.all([
|
||||||
|
make_image(days_since_update()).encode(),
|
||||||
|
make_image(last_update_count).encode(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let image: Uint8Array = new Uint8Array();
|
let last_updated_image: Uint8Array = new Uint8Array();
|
||||||
await update_image();
|
let last_update_count_image: Uint8Array = new Uint8Array();
|
||||||
|
await update_images();
|
||||||
|
|
||||||
Deno.serve({ port: 61264 }, async () => {
|
const image_response = (data: Uint8Array): Response =>
|
||||||
if (new Date().getTime() - last_checked.getTime() >= 60 * 1000) {
|
new Response(data, {
|
||||||
await check_again();
|
|
||||||
await update_image();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Response(image, {
|
|
||||||
headers: { "Content-Type": contentType("png") },
|
headers: { "Content-Type": contentType("png") },
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
await Deno.writeFile("/tmp/poop.png", image);
|
Deno.serve({ port: 61264 }, async (req) => {
|
||||||
|
const url = new URL(req.url);
|
||||||
|
if ((new Date().getTime() - last_checked.getTime()) >= 60 * 1000) {
|
||||||
|
await check_again();
|
||||||
|
await update_images();
|
||||||
|
}
|
||||||
|
|
||||||
|
// could use URLPattern but that would be overkill for this
|
||||||
|
if (url.pathname.match("count")) {
|
||||||
|
return image_response(last_update_count_image);
|
||||||
|
} else {
|
||||||
|
return image_response(last_updated_image);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue