Files
DogFatherGitandClaude Opus 5 39276ef2ee screen6/7/8: der LIVE-Punkt, und eine Benachrichtigung, die stimmt
Filipe: "in dieser kachel soll wenn ich live bin um 20h bis 22h ein
live button der richtig geil ist mit einem live roten punkt symbol am
besten, das soll aufblinken fuer zwei stunden. man soll nicht drauf
druecken koennen aber so dass es auffaellt. ... die leute sollen auch
automatisch eine benarichtigung bekommen um 20 uhr dass ich live bin."

EINE AUSKUNFT, EINE AUSLEGUNG (workspace/assets/js/live.js)
Drei Stellen sollen dasselbe wissen: die Kachel "Draussen" auf der
Startseite, die Kanalkarten auf der Draussen-Seite, die Pulskarte
darunter. Drei Abfragen waeren drei Auslegungen -- und spaetestens
beim naechsten Umbau steht auf der Kachel LIVE und daneben "wartet".

DER DRITTE AUSGANG IST HIER DIE EIGENTLICHE ARBEIT
Die oeffentliche Seite (assets/js/streamplan.js) faengt jeden Fehler
ab und setzt istLive = false. Aus "wir konnten nicht fragen" wird
dort "er sendet nicht" -- wer das liest, macht zu und verpasst den
Stream. Der Dienst SAGT sogar, ob er nachsehen konnte (autoHealthy);
gelesen wird es dort nicht.
Hier gibt es drei Antworten: live / wartet / weiss-nicht. Bei
"weiss nicht" blinkt nichts -- aber es behauptet auch niemand, dass
nichts laeuft. Sechs Antworten des Dienstes durchgespielt.

BLINKEN OHNE FLACKERN
Hausregel vom 12.08.2026: keine aggressiven Flacker-Effekte. Das ist
kein Widerspruch zu "richtig geil", sondern dieselbe Sache: Ein Rot,
das im Sekundentakt umspringt, liest man als "Alarm, ich sehe weg".
Eins, das atmet und einen Saum nach aussen schickt, liest man als
"jetzt gerade". 1,4 Sekunden, ueberall derselbe Takt -- zwei Rhythmen
nebeneinander waeren Unruhe, einer ist ein Herzschlag. Die Pruefung
verlangt ausdruecklich >= 1 s und einen einheitlichen Takt; nach dem
Wort "animation" zu suchen waere auch bei 0,1 s gruen.
Bei Bewegungsarmut steht alles still -- der rote Punkt bleibt
sichtbar, er bewegt sich nur nicht. Im Kontrastmodus sagt es ein
Rahmen, weil Farben dort nichts tragen.

KEIN KNOPF, UND ES SIEHT AUCH NICHT SO AUS
pointer-events: none ist die halbe Antwort; die andere ist die Form.
Etwas, das wie ein Knopf aussieht und nichts tut, ist eine Sackgasse.
Deshalb eine Marke wie auf einer Kamera: Punkt plus Wort. Das Wort
steht auch fuer Vorleseprogramme da -- ein stummer roter Kreis waere
die halbe Auskunft.

DIE KACHEL WIRD UEBER IHR ZIEL ERKANNT, NICHT UEBER DEN NAMEN.
Der Name hat sich in diesem Haus schon zweimal geaendert ("Unsere
Seiten" -> "Draussen"), das Ziel nie. Am 21.09. hat genau dieser
Unterschied eine ganze Hinweisspalte lahmgelegt.

DIE BENACHRICHTIGUNG ENTSCHEIDET DER DIENST, NICHT DIE UHR.
Eine Meldung "er ist live", waehrend er nicht sendet, funktioniert
genau einmal: Beim zweiten Mal weiss jeder, dass sie nichts bedeutet.
Deshalb prueft der Lauf (alle fuenf Minuten) den echten Status; bei
"weiss nicht" wird NICHTS verschickt. Ein Merkmal mit Datum haelt es
bei einer pro Abend -- sonst kaemen in zwei Stunden 24.
Eigene Art "dogfather_live", vorgegeben an und trotzdem abschaltbar:
Wer jeden Abend dieselbe Meldung bekommt und nie hinschaut, schaltet
sonst ALLES ab, und dann erreicht ihn auch keine Aufgabe mehr.

EIN FEHLER, DEN DIE PRUEFUNG GEFANGEN HAT: Der Versand las aus
"push_geraete" -- diese Tabelle gibt es nicht, sie heisst
push_anmeldungen. Der Block steht in einem try/catch; der Fehler
waere still geblieben, und die Benachrichtigung waere nie gekommen.
Die Pruefung verlangt jetzt ausdruecklich, dass die Tabelle im
Schema existiert.

NEU: pruef-livepunkt 49/0, mit drei Gegenproben.
Daneben gruen: pruef-css-klassen 30/0, pruef-push 24/0,
pruef-draussen 39/0, pruef-zwischenspeicher 27/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 09:28:29 +02:00

164 lines
7.5 KiB
JavaScript

/* =====================================================================
DRAUSSEN (21.09.2026) — was die Community-Seite "Unsere Seiten"
braucht, damit sie nichts abschreiben muss.
Filipe: "mach was anderes aus dieser seite oder mach es viel krass
und geiler ... lass dir was uebelst geiles einfallen und ueberrasch
mich ... erstell was was mich von den socken schmeisst. es soll
wirklich sogar ein wow effekt fuer die community ergeben."
---------------------------------------------------------------------
WAS DIESE SEITE VORHER WAR UND WAS DARAN FEHLTE
Zwei Karten mit zwei Adressen. Sauber gebaut, richtig beschriftet --
und trotzdem beantwortete sie keine Frage, die jemand wirklich hat.
Wer im Treff ist, kennt die Website. Der Rabattcode war das Einzige,
wofuer man wiederkam, und den merkt man sich beim ersten Mal.
DIE FRAGE, DIE DIE COMMUNITY WIRKLICH HAT, IST EINE ANDERE: Laeuft
er gerade? Und wenn nicht -- wie lange noch?
Auf die Antwort gibt es bereits einen Dienst im Haus:
postfach.dogfather-universe.com/live-status, derselbe, von dem der
oeffentliche Streamplan lebt. Er wird hier NICHT nachgebaut und auch
nicht durchgereicht -- der Browser fragt ihn direkt, so wie draussen
auch. Nachgemessen, bevor darauf gebaut wurde:
- der Dienst antwortet und meldet sich selbst als gesund
("autoHealthy": true, zuletzt geprueft vor drei Minuten)
- "access-control-allow-origin: *", die Treff-Adresse darf fragen
- die Inhaltsrichtlinie der Treff-Seiten fuehrt postfach bereits
in `connect-src` -- der Abruf waere sonst still blockiert worden
und haette ausgesehen wie ein toter Dienst
---------------------------------------------------------------------
WAS HIER BLEIBT: DIE KANAELE
Die drei TikTok-Accounts stehen als KANAELE in workspace.js -- sie
sind dort die eine Liste, an der die Aufgabenverteilung haengt. Die
Community-Seite bekommt sie von dort und schreibt sie NICHT ab.
Warum das keine Kleinigkeit ist: Am selben Tag stand in dieser Liste
"@hasidog00804" statt "@hasidog0804" -- eine Null zu viel. Zwei
Pruefungen hatten denselben Tippfehler abgeschrieben und waren
deshalb gruen. Eine dritte Abschrift auf einer Seite, die
Zuschauerinnen sehen, waere ein toter Link gewesen, den niemand
meldet, weil niemand weiss, dass er falsch ist.
DIE ADRESSE WIRD EBENFALLS ABGELEITET, nicht zusammengesetzt: Der
Steckbrief weiss bereits, wie eine TikTok-Adresse aus einem Handle
entsteht (KANAELE.tiktok.adresse). Stuende das Muster hier ein
zweites Mal, gaebe es zwei Stellen, die sich bei einer Aenderung
widersprechen koennen.
---------------------------------------------------------------------
WER DAS SEHEN DARF
Jede angemeldete Person. Nicht weil es egal waere, sondern weil hier
nichts steht, was nicht ohnehin oeffentlich ist: Dieselben drei
Accounts sind von dogfather-universe.com aus verlinkt, fuer alle.
Das ist BEWUSST ANDERS als `kanaeleFuer` in workspace-bereiche.js,
wo die Community die Kanalliste ausdruecklich NICHT bekommt. Dort
geht es um die Frage "wohin soll diese Arbeit" -- eine interne
Entscheidung, und wer sie nicht treffen darf, soll auch nicht die
Auswahl sehen. Hier geht es um "wo finde ich ihn". Dieselben Daten,
zwei verschiedene Fragen; deshalb zwei Wege und nicht einer, der
beides halb macht.
===================================================================== */
import express from "express";
import { sitzungLesen, KANAELE } from "./workspace.js";
import { KANAELE as KANAL_ARTEN } from "./workspace-steckbrief.js";
/* DIE FESTE SENDEZEIT.
Sie steht auch in assets/js/streamplan.js der oeffentlichen Seite
(`FIX_STUNDE`). Zwei Zahlen, die dasselbe bedeuten, laufen
irgendwann auseinander -- und es faellt niemandem auf, weil beide
fuer sich plausibel aussehen. Deshalb haelt pruef-draussen die
beiden Orte gegeneinander; verschiebt jemand den Termin und aendert
nur einen, wird die Pruefung rot und sagt, welche Datei fehlt.
WARUM SIE NICHT IN DER VERWALTUNG STEHT: Sie hat sich seit dem
20.08.2026 nicht geaendert. Eine Oberflaeche fuer eine Zahl, die man
einmal im Jahr anfasst, ist mehr Pflege als Nutzen -- und ein Feld,
das niemand benutzt, steht irgendwann falsch. Sobald sich der
Termin oefter bewegt, gehoert er dorthin.
Fuer eine ABWEICHUNG ist sie ohnehin nicht zustaendig: Sendet er
einmal frueher, sagt das der Live-Status, und der kommt vom Dienst,
nicht von dieser Zahl. */
export const SENDEZEIT_STUNDE = 20;
/* =====================================================================
IST ER GERADE LIVE? -- die Antwort fuer den SERVER
=====================================================================
Filipe am 22.09.2026: "die leute sollen auch automatisch eine
benarichtigung bekommen um 20 uhr dass ich live bin."
Die Seiten fragen den Dienst selbst (workspace/assets/js/live.js).
Der Benachrichtigungslauf kann das nicht -- er laeuft im Server,
ohne Browser. Deshalb hier dieselbe Auslegung ein zweites Mal, und
ausdruecklich NUR hier: zwei Stellen im Browser waeren zwei
Auslegungen, Browser und Server sind zwei Welten.
DREI ANTWORTEN, NICHT ZWEI.
"Der Dienst antwortet nicht" ist keine Aussage ueber den Stream,
sondern eine ueber den Dienst. Wer daraus "nicht live" macht,
verschickt entweder nichts (harmlos) oder -- schlimmer -- spaeter
eine Meldung, die nicht stimmt. Hier heisst es "weiss nicht", und
dann wird NICHT verschickt: Lieber keine Benachrichtigung als eine
falsche. Eine Benachrichtigung "er ist live", wenn er es nicht ist,
schafft genau einmal Aufmerksamkeit und danach nie wieder. */
const POSTFACH = "https://postfach.dogfather-universe.com";
export async function liveStatusHolen() {
try {
const steuer = AbortSignal.timeout ? AbortSignal.timeout(6000) : undefined;
const antwort = await fetch(POSTFACH + "/live-status",
{ cache: "no-store", signal: steuer });
if (!antwort.ok) return { zustand: "weissnicht", titel: "" };
const d = await antwort.json();
if (!d || d.ok !== true) return { zustand: "weissnicht", titel: "" };
if (d.live) return { zustand: "live", titel: d.title || "" };
/* Von Hand gesetzt schlaegt den automatischen Pruefer -- dann
spielt dessen Gesundheit keine Rolle. */
if (d.source === "automatisch" && d.autoHealthy === false) {
return { zustand: "weissnicht", titel: "" };
}
return { zustand: "wartet", titel: "" };
} catch {
return { zustand: "weissnicht", titel: "" };
}
}
export const draussenRouter = express.Router();
draussenRouter.get("/workspace/api/draussen", (req, res) => {
const person = sitzungLesen(req);
if (!person) return res.status(401).json({ fehler: "nicht_angemeldet" });
try {
const kanaele = KANAELE.map((k) => {
const ohneAt = k.handle.replace(/^@/, "");
return {
wert: k.wert,
name: k.name,
handle: k.handle,
adresse: KANAL_ARTEN.tiktok.adresse(ohneAt),
satz: k.fuerDraussen || k.text,
};
});
/* KEIN ZWISCHENSPEICHER MIT LAUFZEIT. Die Liste aendert sich nur,
wenn jemand den Quelltext aendert -- dann startet der Dienst neu,
und ein Stempel waere ohnehin hinfaellig. Eine Laufzeit wuerde
hier nur eine Frage beantworten, die niemand stellt. */
res.json({ kanaele, sendeStunde: SENDEZEIT_STUNDE });
} catch (fehler) {
console.error("[workspace] Draussen:", fehler.message);
res.status(500).json({ fehler: "nicht_verfuegbar" });
}
});