From a5e2e353cd5f5d529ba5e809b87ba2f882930278 Mon Sep 17 00:00:00 2001 From: teahubxyz Date: Wed, 21 Oct 2026 22:27:20 +0000 Subject: [PATCH] havre: the check for uploaded card pictures (art vs a real person's photo, grown up) and a clearer reason --- ventures/havre/abilities.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/ventures/havre/abilities.js b/ventures/havre/abilities.js index 443a385..ca2fba4 100644 --- a/ventures/havre/abilities.js +++ b/ventures/havre/abilities.js @@ -460,7 +460,7 @@ export function adultCheck(card, { of18 = false, on = true, made = () => false, if (!of18) return { ok: false, why: "adult photos and clips wait until you say you're 18 or older, under abilities." }; const pics = drawn ? [] : [card.portrait, ...((card.look && card.look.references) || [])].filter(Boolean); if (!drawn && !pics.length) return { ok: false, why: `${card.name} has no picture made here yet (card → look: make one with ai), ${sfw}` }; - if (!pics.every((p) => made(p))) return { ok: false, why: `a picture on their card wasn't made here with ai (it was uploaded, or came from venice), ${sfw}` }; + if (!pics.every((p) => made(p))) return { ok: false, uploaded: true, why: `a picture on their card was uploaded and hasn't been checked yet, ${sfw} If it's art you have the rights to, check it below.` }; const onCard = underage(cardWords(card), UNDERAGE_CARD); if (onCard) return { ok: false, why: `their card says “${onCard}”, which sounds like someone under 18, ${sfw}` }; const now = underage([shot, said]); @@ -468,6 +468,22 @@ export function adultCheck(card, { of18 = false, on = true, made = () => false, return { ok: true, why: "" }; } +/** + * Checking an uploaded picture for an adult character: is it art (drawn, painted, rendered, AI-made) or a photograph + * of a real person, and does everyone in it look grown up? A real person's photo never becomes the reference for an + * adult picture: that's how a deepfake of someone who never agreed is made. Art you have the rights to can. + */ +export const ART_PROMPT = "Look at this picture and answer with one JSON object, nothing else: " + + "{\"kind\": \"art\" or \"photo\", \"adult\": \"yes\", \"no\" or \"unsure\"}. kind is \"art\" for a drawing, painting, " + + "illustration, anime, 3D render, or an obviously AI-generated or stylised image, and \"photo\" for what looks like a real " + + "photograph of a real person. adult is \"yes\" only if everyone shown clearly looks 18 or older."; +/** the checker's answer: { art, adult }, false for anything it didn't clearly say */ +export function parseArt(text) { + const t = str(text, 2000).toLowerCase(); + const kind = /"kind"\s*:\s*"(art|photo)"/.exec(t), adult = /"adult"\s*:\s*"(yes|no|unsure)"/.exec(t); + return { art: !!kind && kind[1] === "art", adult: !!adult && adult[1] === "yes", answered: !!kind && !!adult }; +} + /** * A short fingerprint of a picture (the data: URI a card keeps it as), for the list of pictures this browser made with * AI. It only has to tell this browser's pictures apart; it guards nothing secret.