i like terepi and homestuck 👍 ¦ maid of breath ¦ derse dreamer 😔 ¦ pyrope.net/ew ¦ we call it css crimes but the whole point of css is that it is cascading style sheets which we do not have in posts. i mean, there's still cascading sort of (if i change the font on an element its children will have that font too), and, yes, there is the cohost stylesheets i suppose but. hm. ¦ i like math and computers and computer math ¦ all posts come with a 3 year warranty as well as free customer support

softwawre :)

my recent last.fm listening

pronounsrandom pronouns. basically, any

terezi's head is seen from behind looking at the sky. on the right, it says terezi.pyrope.net and >:]


this account is part of the m,cai ringbug

↑up↑
here
↓down↓

name-color: #008282


my fedi (it works for real because it's run by other people!)
critter.cafe/@mehbark

posts from @mehbark tagged #deno

also:

lexi
@lexi

billion dollar idea: any/all pronouns except instead of actually writing "any/all" in your bio, you use a bot that automatically inserts a new set of pronouns every 10 seconds


mehbark
@mehbark

it doesn't integrate with anything (and is ruined by caching (but not on cohost)), but you can type, e.g, https://pyrope.net/prngnouns?p=any&p=they/them&p=he/him&p=she/her&p=it/its and it will make an image some instantiation of any pronouns like that.

it's a bit big i guess, but it doesn't look too terrible on my profile

question for computer nerds i feel it would be a good idea to let color, size, etc be configurable using the url params, but i avoided doing that because i have a cache for images. i'm thinking that it would probably be better to just remove and remake the image on each request (especially considering that cleaning it up feels too heuristic). idk, would that be fine? would it be too slow? idk? here's the code as it is right now that would probably help (looks bad fsr, idc enough to fix it sorry)
code
import { contentType } from "https://deno.land/std@0.202.0/media_types/mod.ts";
import {
  Image,
  TextLayout,
} from "https://deno.land/x/imagescript@1.2.15/ImageScript.js";

const font = await fetch("https://static.pyrope.net/courier-std-bold.otf")
.then((r) => r.arrayBuffer())
.then((b) => new Uint8Array(b));

// deciding now: pronouns (e.g. he/him) can be at most 32 chars

let images: Map<string, { image: Uint8Array; fetched: number }> = new Map();

function make_image(s: string): Image {
console.log(`MAKING AN IMAGE FOR '${s}' (EXPENSIVE!)`);
let image = Image.renderText(
font,
64,
s,
0,
new TextLayout({ verticalAlign: "center", horizontalAlign: "middle" }),
);

const outline = Image.renderText(
font,
64,
s,
0xff_ff_ff_ff,
new TextLayout({ verticalAlign: "center", horizontalAlign: "middle" }),
);

for (const hshift of [-2, 0, 2]) {
for (const vshift of [-2, 0, 2]) {
image = image.composite(outline, hshift, vshift);
}
}
const text = Image.renderText(
font,
64,
s,
0x00_00_00_ff,
new TextLayout({ verticalAlign: "center", horizontalAlign: "middle" }),
);

const final = image.composite(text);
return final.crop(0, 0, final.width, final.height - 22);
}

async function get_pronoun_image(prn: string): Promise<Uint8Array> {
if (images.has(prn)) {
const entry = images.get(prn)!;
entry.fetched++;
return entry.image;
}
const image = await make_image(prn).encode();
images.set(prn, { image, fetched: 1 });
return image;
}

// the whole cache thing def sketches me out, but people probably won't be that malicious
const MAX_PRN_LENGTH = 32;
const MAX_PRN_CACHE = 64;
// shouldn't really be a problem
const MAX_PRN_CHOICES = 128;

function clean_up() {
if (images.size <= MAX_PRN_CACHE) {
console.log(
`not cleaning up, we only have ${images.size} cached which is less than ${MAX_PRN_CACHE}`,
);
return;
}

// reverse order!
const entries = [...images.entries()].toSorted(([_a, a], [_b, b]) =>
b.fetched - a.fetched
);

console.log("before clean up:", images);
images = new Map(entries.slice(0, MAX_PRN_CACHE));
console.log("after clean up:", images);
}

const image_response = (data: Uint8Array): Response =>
new Response(data, {
headers: { "Content-Type": contentType("png") },
});

Deno.serve({ port: 61265 }, async (req) => {
const prns = (new URL(req.url)).searchParams.getAll("p");

if (prns.some((p) => p.length > MAX_PRN_LENGTH)) {
return new Response(`MAX_PRN_LENGTH = ${MAX_PRN_LENGTH}`, { status: 413 });
}

if (prns.length > MAX_PRN_CHOICES) {
return new Response(`MAX_PRN_CHOICES = ${MAX_PRN_CHOICES}`, {
status: 413,
});
}

const prn = prns[Math.floor(Math.random() * prns.length)] ??
"NONE, APPARENTLY";

const resp = image_response(await get_pronoun_image(prn));
clean_up();
return resp;
});