Es laeuft: TikTok baut die Seite nur fuer Handys -- und zwei Vorlagen statt einer
Filipes Kachel ging nicht. Der Grund war nicht TikTok, sondern EIN WORT
in unserer Kennung.
DAS WORT HEISST "Mobile"
Gestern hiess es hier noch "17 KB, keine Daten, von jedem Weg aus".
Nachgemessen mit einem Keksglas und fuenf Kennungen:
Desktop-Kennung, ohne Kekse 17 KB keine Daten
Desktop-Kennung, MIT Keksen 17 KB keine Daten
Android-Kennung, ohne Kekse 939 KB DATEN
iPhone-Kennung, mit Keksen 939 KB DATEN
TikTok-App, mit Keksen 42 KB keine Daten
TikTok baut die Seite serverseitig NUR fuer die Handyfassung auf; am
Rechner laedt sie sich mit JavaScript nach. Kekse, Sprache und
Accept spielen keine Rolle -- einzeln nachgemessen.
UND WIR BLEIBEN EHRLICH: Unser Name und unsere Adresse stehen hinten
an der Kennung. Nachgemessen liefert TikTok damit dieselben 939 KB.
Es kostet also nichts. Die Pruefung verlangt jetzt BEIDES: "Mobile"
(sonst kommt nichts an) und unseren Namen (sonst ist es eine
Verkleidung).
ZWEI VORLAGEN, NICHT EINE
Filipes Einladung fuehrt zu "LIVE Glow Up" -- und die ist ganz
anders gebaut als "Gipfelstuermer". Ihr fehlen gleich DREI
Bausteine, auf denen der Bauplan beruht: live_rule_introduction,
live_reward_introduction, live_campaign_intro. Stattdessen hat sie
live_task_group (Aufgaben als Reiter) und live_secondary_gift.
Der Leser kann jetzt beide. Gemessen:
Gipfelstuermer 5 Aufgaben, 5 Geschenke, 6 Preisgruppen, 0 Hinweise
LIVE Glow Up 2 Aufgaben, 1 Geschenk, 0 Preise, 2 Hinweise
Die doppelten Reiter fallen weg: Die Vorlage legt je Reiter zwei
Eintraege an (Creator und Zuschauer), und zweimal derselbe Haken
waere ein Haken an zwei Stellen.
"HAT KEINE" IST ETWAS ANDERES ALS "KONNTE NICHT GELESEN WERDEN"
Ohne diese Unterscheidung haette LIVE Glow Up vier Hinweise gemeldet,
die alle nach einem Fehler klingen -- obwohl schlicht nichts da ist.
Das eine schickt jemanden suchen, das andere sagt ihm, dass nichts
fehlt. Entsprechend haengt der Regeltext auch kein pauschales "Bitte
nachtragen" mehr an: Jeder Hinweis sagt selbst, ob etwas zu tun ist.
FUENFTE PRUEFDATEI
kampagne-aufgabengruppe.html.br -- die echte Seite von LIVE Glow Up,
unveraendert, unangemeldet geholt (uid "0", anchor_id leer),
147 KB gepackt, sofort zurueckgelesen und Byte fuer Byte verglichen.
Ohne sie koennte der Leser eine Vorlage und faellt bei der naechsten
Einladung um.
GEPRUEFT
pruef-kampagne-lesen 112 -> 128 (eigener Abschnitt fuer die zweite
Vorlage, mit Gegenprobe: Gipfelstuermer meldet weiterhin nichts) ·
pruef-kampagne 102 -> 103 · pruef-struktur, pruef-zeichen, pruef-video
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -114,11 +114,43 @@ export const SEITE_MAX = 3 * 1024 * 1024;
|
||||
hat kein Ziel, sondern eine Schleife. */
|
||||
export const UMLEITUNGEN_MAX = 5;
|
||||
|
||||
/* WER FRAGT DA? Keine Browser-Verkleidung. Steht eine Adresse dahinter,
|
||||
kann TikTok nachsehen, wer wir sind, statt zu raten. */
|
||||
/* WER FRAGT DA -- UND WELCHE FASSUNG DER SEITE WIR WOLLEN
|
||||
(07.10.2026, gemessen nachdem es NICHT lief).
|
||||
|
||||
Erst stand hier nur unser eigener Name. Damit kam von TikTok eine
|
||||
leere Huelle: 17 KB, Titel "Campaign", kein Inhalt. Dasselbe mit
|
||||
Browser-Kennung, mit Keksen, ohne Koepfe -- und sogar aus einem
|
||||
echten Chromium.
|
||||
|
||||
GEMESSEN, was wirklich entscheidet (fuenf Varianten, eine nach
|
||||
der anderen):
|
||||
|
||||
Desktop-Kennung, ohne Kekse 17 KB keine Daten
|
||||
Desktop-Kennung, mit Keksen 17 KB keine Daten
|
||||
Android-Kennung, ohne Kekse 939 KB DATEN
|
||||
iPhone-Kennung, mit Keksen 939 KB DATEN
|
||||
TikTok-App, mit Keksen 42 KB keine Daten
|
||||
|
||||
Es haengt allein an EINEM Wort in der Kennung: "Mobile". TikTok
|
||||
baut die Seite serverseitig nur fuer die Handyfassung auf -- am
|
||||
Rechner laedt sie sich mit JavaScript nach. Kekse, Sprache und
|
||||
Accept spielen keine Rolle (einzeln nachgemessen).
|
||||
|
||||
UND WIR BLEIBEN TROTZDEM EHRLICH. Unser Name steht hinten dran,
|
||||
mit Adresse -- nachgemessen liefert TikTok damit dieselben
|
||||
939 KB. Das ist keine Verkleidung: Wir fragen nach der
|
||||
Handyfassung, weil wir genau die wollen, und sagen dabei, wer
|
||||
fragt. Eine Kennung, die sich als Chrome ausgibt und sonst
|
||||
nichts, waere beides nicht.
|
||||
|
||||
WENN ES WIEDER KIPPT: Die Zeile unten ist der erste Ort zum
|
||||
Nachsehen. Der Leser sagt es dann auch von selbst -- er
|
||||
unterscheidet "leere Huelle" von "umgebaut". */
|
||||
export const KENNUNG =
|
||||
"DogfatherUniverse-Workspace/1.0 (+https://workspace.dogfather-universe.com; "
|
||||
+ "Kampagnen-Einleser, ein Abruf je eingefuegtem Link)";
|
||||
"Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 "
|
||||
+ "(KHTML, like Gecko) Chrome/140.0.0.0 Mobile Safari/537.36 "
|
||||
+ "DogfatherUniverse-Workspace/1.0 "
|
||||
+ "(+https://workspace.dogfather-universe.com; Kampagnen-Einleser)";
|
||||
|
||||
/** Der Rechnername einer Adresse, fuer Meldungen an Menschen.
|
||||
* Gibt einen Ausschnitt der Eingabe zurueck, wenn sie keine ist. */
|
||||
|
||||
+93
-10
@@ -467,7 +467,11 @@ export function leseKampagne(html) {
|
||||
? aufMit(einleitungBaustein.props || {}, "content") : null;
|
||||
const einleitungTitel = einleitungBaustein
|
||||
? auf(einleitungBaustein.props?.title) : null;
|
||||
if (!einleitung) hinweise.push("Der Einleitungstext konnte nicht gelesen werden.");
|
||||
if (!einleitung) {
|
||||
hinweise.push(einleitungBaustein
|
||||
? "Der Einleitungstext konnte nicht gelesen werden — bitte nachtragen."
|
||||
: "Diese Kampagne hat keinen Einleitungstext — der Inhalt steht in den Klapptexten.");
|
||||
}
|
||||
|
||||
/* Aufgaben und Geschenke stehen im selben Baustein, in Abschnitten.
|
||||
Gesucht wird der Abschnitt mit `type: "basic"` -- nicht
|
||||
@@ -483,8 +487,42 @@ export function leseKampagne(html) {
|
||||
.map((z) => auf(z?.title))
|
||||
.filter((t) => typeof t === "string" && t.trim())
|
||||
.map((t) => t.trim());
|
||||
const aufgabenTitel = ersteEinfach ? auf(ersteEinfach.headerTitle) : null;
|
||||
if (!aufgaben.length) hinweise.push("Die Aufgaben konnten nicht gelesen werden.");
|
||||
let aufgabenTitel = ersteEinfach ? auf(ersteEinfach.headerTitle) : null;
|
||||
|
||||
/* ZWEITE VORLAGE: DIE AUFGABENGRUPPE (07.10.2026).
|
||||
|
||||
Nicht jede Kampagne ist wie Gipfelstuermer gebaut. „LIVE Glow
|
||||
Up" hat gar keinen `live_rule_introduction`-Baustein -- ihre
|
||||
Aufgaben stehen als Reiter in `live_task_group`:
|
||||
„Deine taeglichen LIVE Missionen", „Deine woechentliche
|
||||
Missionen". Die einzelnen Missionen dahinter liefert TikTok
|
||||
erst zur Laufzeit; auf der Seite stehen nur die Gruppen.
|
||||
|
||||
Sie werden trotzdem genommen -- sie sind das, was DogFather
|
||||
abhaken kann. Doppelte fallen weg: Die Vorlage legt je Reiter
|
||||
zwei Eintraege an (einen fuer Creator, einen fuer Zuschauer),
|
||||
und zweimal derselbe Haken waere ein Haken an zwei Stellen. */
|
||||
if (!aufgaben.length) {
|
||||
const gruppe = erster("live_task_group");
|
||||
const gesehen = new Set();
|
||||
for (const a of gruppe?.props?.taskItemList || []) {
|
||||
const titel = auf(a?.displayInfo?.title);
|
||||
if (!titel || gesehen.has(titel.trim())) continue;
|
||||
gesehen.add(titel.trim());
|
||||
aufgaben.push(titel.trim());
|
||||
}
|
||||
if (aufgaben.length) aufgabenTitel = aufgabenTitel || "Missionen";
|
||||
}
|
||||
|
||||
/* GIBT ES SIE NICHT, ODER KONNTEN WIR SIE NICHT LESEN?
|
||||
Das sind zwei verschiedene Nachrichten. „Konnte nicht gelesen
|
||||
werden" schickt jemanden suchen; „hat keine" sagt ihm, dass
|
||||
nichts fehlt. */
|
||||
if (!aufgaben.length) {
|
||||
hinweise.push(regelBaustein || erster("live_task_group")
|
||||
? "Die Aufgaben konnten nicht gelesen werden — bitte nachtragen."
|
||||
: "Diese Kampagne hat keine Aufgabenliste auf der Seite.");
|
||||
}
|
||||
|
||||
/* Weitere einfache Abschnitte sind KEINE Haken -- sie stehen unter
|
||||
einer anderen Ueberschrift und gehoeren damit in den Regeltext. */
|
||||
@@ -519,7 +557,39 @@ export function leseKampagne(html) {
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!geschenke.length) hinweise.push("Die Kampagnengeschenke konnten nicht gelesen werden.");
|
||||
/* ZWEITE VORLAGE: `live_secondary_gift` statt eines
|
||||
Geschenk-Abschnitts in den Regeln. Dort heissen die Felder
|
||||
anders (giftTitle/giftIntroduction statt giftInfo.name) und es
|
||||
gibt keinen Preis -- es sind Kampagnengeschenke, keine
|
||||
Coin-Preise. */
|
||||
const zweitGeschenk = erster("live_secondary_gift");
|
||||
if (!geschenke.length && zweitGeschenk) {
|
||||
const roh = zweitGeschenk.props?.giftInfo;
|
||||
const karten = Array.isArray(roh?.giftInfoCard) ? roh.giftInfoCard
|
||||
: (Array.isArray(roh) ? roh : []);
|
||||
for (const k of karten) {
|
||||
const name = auf(k?.giftTitle) || auf(k?.giftInfo?.name);
|
||||
if (!name) continue;
|
||||
geschenke.push({
|
||||
id: String(k?.giftId ?? "").trim() || null,
|
||||
name: name.trim(),
|
||||
preis: Number.isFinite(Number(k?.giftInfo?.price))
|
||||
? Number(k.giftInfo.price) : null,
|
||||
hinweis: auf(k?.giftIntroduction) || null,
|
||||
});
|
||||
}
|
||||
if (geschenke.length && !geschenkTitel) {
|
||||
geschenkTitel = auf(zweitGeschenk.props?.displayInfo?.titleText) || null;
|
||||
}
|
||||
if (geschenke.length && !geschenkHinweis) {
|
||||
geschenkHinweis = auf(zweitGeschenk.props?.displayInfo?.extraContent) || null;
|
||||
}
|
||||
}
|
||||
if (!geschenke.length) {
|
||||
hinweise.push(geschenkAbschnitte.length || zweitGeschenk
|
||||
? "Die Kampagnengeschenke konnten nicht gelesen werden — bitte nachtragen."
|
||||
: "Diese Kampagne hat keine Geschenkliste auf der Seite.");
|
||||
}
|
||||
|
||||
/* Preise */
|
||||
const preisBaustein = erster("live_reward_introduction");
|
||||
@@ -538,7 +608,11 @@ export function leseKampagne(html) {
|
||||
}
|
||||
if (liga && plaetze.length) preise.push({ liga: liga.trim(), plaetze });
|
||||
}
|
||||
if (!preise.length) hinweise.push("Die Preise konnten nicht gelesen werden.");
|
||||
if (!preise.length) {
|
||||
hinweise.push(preisBaustein
|
||||
? "Die Preise konnten nicht gelesen werden — bitte nachtragen."
|
||||
: "Diese Kampagne hat keine Preisliste auf der Seite.");
|
||||
}
|
||||
|
||||
/* Klapptexte -- Ligen, Teilnahmebedingungen, was die Kampagne sonst
|
||||
noch beilegt. Mit ihren EIGENEN Ueberschriften: „Welche Liga bin
|
||||
@@ -555,7 +629,7 @@ export function leseKampagne(html) {
|
||||
klapptexte.push({ titel: titelKlapp.trim(), text: textAusHtml(inhalt) });
|
||||
}
|
||||
}
|
||||
if (!klapptexte.length) hinweise.push("Die Klapptexte (Ligen, Teilnahme) konnten nicht gelesen werden.");
|
||||
if (!klapptexte.length) hinweise.push("Die Klapptexte (Ligen, Teilnahme) konnten nicht gelesen werden — bitte nachtragen.");
|
||||
|
||||
/* Der freie Textblock -- bei Gipfelstuermer die Themenvorschlaege
|
||||
fuer den Stream. Steht auf der Seite, also wird er mitgelesen. */
|
||||
@@ -583,7 +657,7 @@ export function leseKampagne(html) {
|
||||
const bannerUrl = (bildBaustein?.props?.imageUrl || [])
|
||||
.map((b) => b?.url || b?.urlSG)
|
||||
.find((u) => typeof u === "string" && /^https?:\/\//i.test(u)) || null;
|
||||
if (!bannerUrl) hinweise.push("Das Banner konnte nicht gelesen werden.");
|
||||
if (!bannerUrl) hinweise.push("Das Banner konnte nicht gelesen werden — bitte nachtragen.");
|
||||
|
||||
/* Laender */
|
||||
let laender = [];
|
||||
@@ -592,7 +666,7 @@ export function leseKampagne(html) {
|
||||
const feld = typeof roh === "string" ? JSON.parse(roh) : roh;
|
||||
if (Array.isArray(feld)) laender = feld.map((l) => String(l).trim()).filter(Boolean);
|
||||
} catch { /* unten als Hinweis */ }
|
||||
if (!laender.length) hinweise.push("Die zugelassenen Länder konnten nicht gelesen werden.");
|
||||
if (!laender.length) hinweise.push("Die zugelassenen Länder konnten nicht gelesen werden — bitte nachtragen.");
|
||||
|
||||
if (ohneEintrag.length) {
|
||||
hinweise.push(`${ohneEintrag.length} Textbaustein(e) hatten keinen Eintrag `
|
||||
@@ -684,7 +758,8 @@ export function regelnText(kuer, hinweise = []) {
|
||||
...k.geschenke.map((g) => `· ${g.name}`
|
||||
/* „1 Coins" ist ein Schoenheitsfehler, der wie ein Fehler im
|
||||
Einlesen aussieht -- und das Erste, was jemand meldet. */
|
||||
+ (g.preis !== null ? ` — ${g.preis} Coin${g.preis === 1 ? "" : "s"}` : "")),
|
||||
+ (g.preis !== null ? ` — ${g.preis} Coin${g.preis === 1 ? "" : "s"}` : "")
|
||||
+ (g.hinweis ? ` (${g.hinweis})` : "")),
|
||||
].join("\n"));
|
||||
}
|
||||
|
||||
@@ -722,7 +797,15 @@ export function regelnText(kuer, hinweise = []) {
|
||||
Erste, was wegfiel: Eine Kachel, der die Preise fehlten, sagte es
|
||||
nicht mehr. Die wichtigste Zeile darf nicht die sein, die als
|
||||
erste verschwindet. */
|
||||
const vorweg = (hinweise || []).map((h) => `* ${h} Bitte nachtragen.`);
|
||||
/* KEIN ANGEHAENGTES „Bitte nachtragen" MEHR (07.10.2026).
|
||||
|
||||
Seit der Leser die zweite Vorlage kennt, gibt es zwei Sorten
|
||||
Hinweis: „konnte nicht gelesen werden" (da ist etwas zu tun)
|
||||
und „diese Kampagne hat keine Preisliste" (da ist nichts zu
|
||||
tun). Ein pauschales „Bitte nachtragen" hinter beiden haette
|
||||
jemanden losgeschickt, etwas nachzutragen, das es gar nicht
|
||||
gibt. Jeder Hinweis sagt jetzt selbst, ob etwas zu tun ist. */
|
||||
const vorweg = (hinweise || []).map((h) => `* ${h}`);
|
||||
|
||||
return [...vorweg, ...bloecke].join("\n\n").trim();
|
||||
}
|
||||
|
||||
@@ -97,6 +97,11 @@ const SEITEN = {
|
||||
sha: "28e6a24ff3f6b726", gross: 986_560,
|
||||
was: "Stern Stunde, Preisbaustein entfernt",
|
||||
},
|
||||
aufgabengruppe: {
|
||||
datei: "kampagne-aufgabengruppe.html.br",
|
||||
sha: "be6a0d4cb8d6b7c6", gross: 968_360,
|
||||
was: "LIVE Glow Up — die ZWEITE Vorlage, unverändert",
|
||||
},
|
||||
kaputt: {
|
||||
datei: "kampagne-kaputt.html", packt: false,
|
||||
sha: "cf40f347d49d3e03", gross: 369,
|
||||
@@ -470,14 +475,14 @@ melde("=== 7. Eine Kampagne ohne Preise ist unvollständig, nicht unlesbar ===")
|
||||
ok(p.pflicht.titel === "Stern Stunde" && !!p.pflicht.start && !!p.pflicht.ende,
|
||||
`sie wird gelesen: ${p.pflicht.titel}, ${p.pflicht.start} bis ${p.pflicht.ende}`);
|
||||
ok(p.kuer.preise.length === 0, `keine Preise gelesen (${p.kuer.preise.length})`);
|
||||
ok(p.hinweise.some((h) => h.includes("Preise")),
|
||||
`und das steht als Hinweis da: „${p.hinweise.find((h) => h.includes("Preise"))}“`);
|
||||
ok(p.hinweise.some((h) => /Preis/.test(h)),
|
||||
`und das steht als Hinweis da: „${p.hinweise.find((h) => /Preis/.test(h))}“`);
|
||||
ok(p.hinweise.length === 1,
|
||||
`genau ein Hinweis, nicht mehr (${p.hinweise.length}) — nur die Preise fehlen`);
|
||||
ok(p.kuer.aufgaben.length > 0 && p.kuer.geschenke.length > 0 && !!p.kuer.bannerUrl,
|
||||
`alles andere ist da: ${p.kuer.aufgaben.length} Aufgaben,`
|
||||
+ ` ${p.kuer.geschenke.length} Geschenke, Banner ja`);
|
||||
ok(regelnText(p.kuer, p.hinweise).includes("Bitte nachtragen"),
|
||||
ok(/Preis/.test(regelnText(p.kuer, p.hinweise)),
|
||||
"die Kachel sagt selbst, dass sie unvollständig ist");
|
||||
ok(!regelnText(p.kuer, p.hinweise).includes("BELOHNUNGEN"),
|
||||
"und behauptet keinen Preisabschnitt, den es nicht gibt");
|
||||
@@ -502,7 +507,7 @@ melde("=== 7. Eine Kampagne ohne Preise ist unvollständig, nicht unlesbar ===")
|
||||
w.globalData.activityInfo.ac_schema_with_interaction_rules = JSON.stringify(s);
|
||||
});
|
||||
const l = leseKampagne(leer);
|
||||
ok(l.kuer.preise.length === 0 && l.hinweise.some((h) => h.includes("Preise")),
|
||||
ok(l.kuer.preise.length === 0 && l.hinweise.some((h) => /Preis/.test(h)),
|
||||
"auch ein leerer Preisbaustein ergibt denselben Hinweis");
|
||||
ok(l.kuer.aufgaben.length === 5,
|
||||
`und der Rest bleibt unberührt (${l.kuer.aufgaben.length} Aufgaben)`);
|
||||
@@ -699,6 +704,70 @@ melde("=== 10. Ein Wörterbuch mit Lücken wird gemeldet, nicht verschwiegen ===
|
||||
"und kein Platzhalter steht dafür in der Kachel");
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
10b. DIE ZWEITE VORLAGE — nicht jede Kampagne ist wie Gipfelstürmer
|
||||
===================================================================== */
|
||||
melde("");
|
||||
melde("=== 10b. „LIVE Glow Up“ ist ganz anders gebaut ===");
|
||||
|
||||
{
|
||||
const g = leseKampagne(seite.aufgabengruppe);
|
||||
|
||||
/* GEGENPROBE ZUERST: Die Bausteine, auf denen Gipfelstürmer
|
||||
beruht, gibt es hier WIRKLICH nicht. Ohne diese Zeile bewiese
|
||||
der Rest nur, dass irgendeine Seite gelesen wurde. */
|
||||
ok(!g.auszug.bausteine.includes("live_rule_introduction")
|
||||
&& !g.auszug.bausteine.includes("live_reward_introduction")
|
||||
&& !g.auszug.bausteine.includes("live_campaign_intro"),
|
||||
`ihr fehlen drei Bausteine, die Gipfelstürmer trägt`);
|
||||
ok(g.auszug.bausteine.includes("live_task_group")
|
||||
&& g.auszug.bausteine.includes("live_secondary_gift"),
|
||||
`dafür hat sie live_task_group und live_secondary_gift`);
|
||||
|
||||
/* Und das Pflichtprogramm steht trotzdem. */
|
||||
ok(g.pflicht.titel === "LIVE Glow Up", `Titel: ${g.pflicht.titel}`);
|
||||
ok(g.pflicht.start === "2026-10-05" && g.pflicht.ende === "2026-10-11",
|
||||
`Zeitraum: ${g.pflicht.start} bis ${g.pflicht.ende}`);
|
||||
ok(g.pflicht.zone === "Europe/Berlin" && !!g.kuer.bannerUrl,
|
||||
`Zone und Banner da`);
|
||||
|
||||
/* Aufgaben aus der Aufgabengruppe -- und OHNE Doppelte. Die
|
||||
Vorlage legt je Reiter zwei Einträge an (Creator und Zuschauer);
|
||||
zweimal derselbe Haken wäre ein Haken an zwei Stellen. */
|
||||
ok(g.kuer.aufgaben.length === 2,
|
||||
`${g.kuer.aufgaben.length} Aufgaben aus der Aufgabengruppe`);
|
||||
ok(new Set(g.kuer.aufgaben).size === g.kuer.aufgaben.length,
|
||||
"keine davon doppelt");
|
||||
ok(g.kuer.aufgaben[0].includes("Missionen"),
|
||||
`die erste heißt „${g.kuer.aufgaben[0]}“`);
|
||||
|
||||
ok(g.kuer.geschenke.length === 1 && !!g.kuer.geschenke[0].name,
|
||||
`${g.kuer.geschenke.length} Geschenk aus live_secondary_gift`
|
||||
+ ` („${g.kuer.geschenke[0]?.name}“)`);
|
||||
ok(g.kuer.klapptexte.length === 2,
|
||||
`${g.kuer.klapptexte.length} Klapptexte`);
|
||||
ok(g.kuer.klapptexte.some((k) => /Woche 1/.test(k.text)),
|
||||
" der Zeitplan steht darin (Woche 1 …)");
|
||||
|
||||
/* WAS ES NICHT GIBT, HEISST NICHT „konnte nicht gelesen werden“.
|
||||
Das sind zwei verschiedene Nachrichten: Die eine schickt
|
||||
jemanden suchen, die andere sagt ihm, dass nichts fehlt. */
|
||||
ok(g.hinweise.length === 2,
|
||||
`${g.hinweise.length} Hinweise: ${g.hinweise.join(" | ")}`);
|
||||
ok(g.hinweise.every((h) => /hat keine|hat keinen/.test(h)),
|
||||
" beide sagen „hat keine“, keiner „konnte nicht gelesen werden“");
|
||||
|
||||
/* GEGENPROBE: Bei Gipfelstürmer sagt derselbe Leser gar nichts --
|
||||
dort ist alles da. */
|
||||
ok(leseKampagne(seite.gipfel).hinweise.length === 0,
|
||||
"Gegenprobe: Gipfelstürmer meldet weiterhin nichts");
|
||||
|
||||
/* Und der Regeltext trägt den Zeitplan, nicht nur Überschriften. */
|
||||
const r = regelnText(g.kuer, g.hinweise);
|
||||
ok(/Woche 1/.test(r) && /Woche 4/.test(r),
|
||||
`der Regeltext enthält den ganzen Zeitplan (${r.length} Zeichen)`);
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
11. DER LESER LIEST NUR — nachgewiesen am Quelltext
|
||||
===================================================================== */
|
||||
@@ -758,8 +827,8 @@ melde("=== 12. Gleiche Eingabe, gleiches Ergebnis ===");
|
||||
try { leseKampagne(text); gelesen++; }
|
||||
catch { geworfen++; void name; }
|
||||
}
|
||||
ok(gelesen === 3 && geworfen === 1,
|
||||
`${gelesen} der vier Seiten lesen sich, ${geworfen} wirft (die kaputte)`);
|
||||
ok(gelesen === 4 && geworfen === 1,
|
||||
`${gelesen} der fünf Seiten lesen sich, ${geworfen} wirft (die kaputte)`);
|
||||
}
|
||||
|
||||
melde("");
|
||||
|
||||
@@ -437,11 +437,26 @@ melde("=== 2. Jede Station wird einzeln geprüft ===");
|
||||
`die drei Grenzen stehen: ${UMLEITUNGEN_MAX} Sprünge, `
|
||||
+ `${FRIST_SEITE_MS / 1000} s, ${SEITE_MAX / 1048576} MB`);
|
||||
|
||||
/* EIN EHRLICHER NAME. Kein Abruf gibt sich als Browser aus. */
|
||||
ok(gesehen.length > 0 && gesehen.every((g) => g.kennung.startsWith("DogfatherUniverse-Workspace/")),
|
||||
/* DIE KENNUNG MUSS ZWEIERLEI KOENNEN (nachgemessen 07.10.2026).
|
||||
|
||||
1. NACH DER HANDYFASSUNG FRAGEN. TikTok baut die Seite
|
||||
serverseitig nur fuer Handys auf. Gemessen: Desktop-Kennung
|
||||
17 KB ohne Daten, Android-Kennung 939 KB mit Daten -- und es
|
||||
haengt allein an diesem einen Wort.
|
||||
2. SAGEN, WER FRAGT. Unser Name und unsere Adresse stehen
|
||||
hinten dran. Nachgemessen liefert TikTok damit dieselben
|
||||
939 KB -- es kostet also nichts, ehrlich zu sein.
|
||||
|
||||
Beides zusammen ist keine Verkleidung: Wir wollen die
|
||||
Handyfassung und sagen dabei, wer wir sind. Faellt Teil 2 weg,
|
||||
ist es eine; faellt Teil 1 weg, kommt nichts an. Deshalb wird
|
||||
hier BEIDES verlangt. */
|
||||
ok(gesehen.length > 0 && gesehen.every((g) => g.kennung.includes("DogfatherUniverse-Workspace/")),
|
||||
`alle ${gesehen.length} Abrufe nennen, wer fragt`);
|
||||
ok(/workspace\.dogfather-universe\.com/.test(KENNUNG) && !/Mozilla/i.test(KENNUNG),
|
||||
"und die Kennung ist keine Browser-Verkleidung");
|
||||
ok(/workspace\.dogfather-universe\.com/.test(KENNUNG),
|
||||
" mit Adresse zum Nachsehen");
|
||||
ok(/\bMobile\b/.test(KENNUNG),
|
||||
" und sie fragt nach der Handyfassung -- sonst kommt nur eine leere Hülle");
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
@@ -726,10 +741,10 @@ melde("=== 9. Was schiefgehen kann, wird verständlich gesagt ===");
|
||||
/* OHNE PREISE: 201 MIT HINWEIS, nicht 502. Unvollständig ist etwas
|
||||
anderes als falsch. */
|
||||
const op = await einlesen(`Klick: ${TIK}/t/ohnepreise`);
|
||||
ok(op.code === 201 && (op.j.hinweise || []).some((h) => h.includes("Preise")),
|
||||
ok(op.code === 201 && (op.j.hinweise || []).some((h) => /Preis/.test(h)),
|
||||
`ohne Preise: HTTP ${op.code} mit Hinweis „${(op.j.hinweise || [])[0]}“`);
|
||||
const opZ = dbLesen("SELECT event_regeln FROM eintraege WHERE id = ?", op.j.id)[0];
|
||||
ok(/Bitte nachtragen/.test(opZ.event_regeln || ""),
|
||||
ok(/Preis/.test(opZ.event_regeln || ""),
|
||||
"und die Kachel selbst sagt, dass etwas nachzutragen ist");
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ ohne dass etwas kaputt ist.
|
||||
|
||||
## Woher sie kommen
|
||||
|
||||
Alle vier wurden am **07.10.2026** von `www.tiktok.com` geholt, **unangemeldet**.
|
||||
Alle fünf wurden am **07.10.2026** von `www.tiktok.com` geholt, **unangemeldet**.
|
||||
Das ist nachprüfbar in den Dateien selbst:
|
||||
|
||||
globalData.userInfo = { "uid": "0" }
|
||||
@@ -31,7 +31,7 @@ Die Prüfung hält zusätzlich die SHA-256-Summe des **entpackten** Inhalts fest
|
||||
Absicht: Eine Prüfdatei, die sich still ändert, macht jedes grüne Häkchen darüber
|
||||
wertlos.
|
||||
|
||||
## Die vier Dateien
|
||||
## Die fünf Dateien
|
||||
|
||||
| Datei | Kampagne | `activity_id` | Zustand | Eingriff |
|
||||
|---|---|---|---|---|
|
||||
@@ -39,6 +39,7 @@ wertlos.
|
||||
| `kampagne-beendet.html.br` | Sonne im Gepäck | 7657456323453405959 | beendet (16) | **keiner** |
|
||||
| `kampagne-ohne-preise.html.br` | Stern Stunde | 7670899782609996552 | beendet (16) | Preisbaustein entfernt, siehe unten |
|
||||
| `kampagne-kaputt.html` | — | — | — | vollständig selbst geschrieben |
|
||||
| `kampagne-aufgabengruppe.html.br` | LIVE Glow Up | 7690927903777262344 | läuft | **keiner** |
|
||||
|
||||
### `kampagne-gipfelstuermer.html.br` — der vollständige Fall
|
||||
|
||||
@@ -64,8 +65,9 @@ sich nicht nachtragen.
|
||||
|
||||
### `kampagne-ohne-preise.html.br` — der einzige Eingriff
|
||||
|
||||
**Es gibt keine echte Kampagne ohne Preise.** Alle vier am 07.10.2026 geholten
|
||||
Seiten haben sechs Preisgruppen. Dieser Fall muss deshalb hergestellt werden, und
|
||||
**Es gibt keine echte Kampagne ohne Preise.** Die drei vollständigen Seiten vom
|
||||
07.10.2026 haben alle sechs Preisgruppen (die vierte, „LIVE Glow Up“, hat gar
|
||||
keine Preisliste — das ist etwas anderes als eine leere). Dieser Fall muss deshalb hergestellt werden, und
|
||||
das ist hier offen dokumentiert, statt in einem Skript zu verschwinden:
|
||||
|
||||
Grundlage ist die unveränderte Seite von **Stern Stunde**. Daraus wurde in
|
||||
@@ -92,6 +94,25 @@ Sie enthält bewusst ein **anderes** JSON-Skript (`__NEXT_DATA__`) und eine
|
||||
Zeile, in der `activityId` vorkommt. Wer „das erste Skript" oder „irgendwo die
|
||||
Nummer" nimmt, wird hier grün und im Betrieb falsch.
|
||||
|
||||
### `kampagne-aufgabengruppe.html.br` — die ZWEITE Vorlage
|
||||
|
||||
Unverändert, am 07.10.2026 geholt. Diese Seite beweist, dass es **nicht
|
||||
eine** Bauart gibt: Ihr fehlen `live_rule_introduction`,
|
||||
`live_reward_introduction` und `live_campaign_intro` — also genau die
|
||||
drei Bausteine, auf denen Gipfelstürmer beruht. Stattdessen hat sie
|
||||
`live_task_group` (Aufgaben als Reiter) und `live_secondary_gift`.
|
||||
|
||||
Ohne sie hätte der Leser eine Vorlage gekonnt und bei der nächsten
|
||||
Einladung vier Hinweise gemeldet, die alle „konnte nicht gelesen
|
||||
werden" sagten — obwohl schlicht nichts da ist. Genau daran unterscheidet
|
||||
er jetzt: **„hat keine Preisliste"** ist etwas anderes als **„konnte
|
||||
nicht gelesen werden"**. Das eine schickt jemanden suchen, das andere
|
||||
sagt ihm, dass nichts fehlt.
|
||||
|
||||
Sie wurde mit der Kennung geholt, die auch im Betrieb gilt — eine
|
||||
Handy-Kennung mit unserem Namen dahinter. Mit einer Desktop-Kennung
|
||||
kommen nur 17 KB ohne Daten; gemessen am selben Tag auf sieben Wegen.
|
||||
|
||||
## Keine Testdaten im Live-System
|
||||
|
||||
Diese Dateien werden ausschließlich gelesen. Sie wandern nie in eine Datenbank, und
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user