Der Weg ueber die TikTok-Datei des Creators ist entfernt
Filipe, mit den drei Knoepfen im Bild: "ich will nur dass wir manager
scouts, dogfather oder spicy sachen eintragen koennen und nicht die
creator. ich will keine daten von denen kriegen, nur wir."
Gebaut am Vormittag, am Nachmittag wieder ausgebaut. Der Weg war
technisch in Ordnung -- und er war der einzige, bei dem ein CREATOR uns
etwas gibt: seine eigene Datenkopie aus der TikTok-App. Genau das soll
nicht sein. Es bleiben die beiden Wir-Wege: die eigene Datei und die
Backstage-Tabelle der Agentur.
VOLLSTAENDIG ENTFERNT, NICHT VERSTECKT:
- beide Schnittstellen (/tiktok-datei und /tiktok-datei/vorschau)
- der Leser workspace-tiktok-datei.js (263 Zeilen)
- Knopf, Fenster, Dateiauswahl, Vorschau, Stilregeln
- der fertige Text, der einen Creator um seine Daten bittet
- der Erklaersatz unter der Knopfreihe
Ein Weg, der nur unsichtbar ist, ist weiterhin ein Weg -- wer die
Adresse kennt, benutzt ihn. Und eine Bitte an einen Creator um seine
Daten soll in diesem Haus nirgends mehr stehen, auch nicht in einem
Fenster, das niemand oeffnet.
GEPRUEFT WIRD JETZT DIE ABWESENHEIT, an drei Stellen: Knopf weg,
Fenster weg, und die Schnittstelle antwortet DOGFATHER mit 404 -- dem
staerksten Zugang, den es gibt. Bekommt er 404, bekommt ihn jeder.
Daneben die Gegenprobe, dass der Backstage-Weg weiterhin mit 200
antwortet; sonst bewiese das 404 nur einen Tippfehler.
pruef-tiktok-datei.mjs (47 Pruefungen) faellt mit dem Weg weg. Die
Zahl sinkt dadurch, und das ist hier richtig: Sie pruefte etwas, das
es nicht mehr gibt. Was bleibt, sind sechs Pruefungen, die das
Fehlen sichern -- pruef-backstage-import 63 -> 66.
NEBENBEI GEDREHT, NICHT GELOESCHT: pruef-leistung-optik behauptete
noch die Regel vom 07.09. ("beim Manager fehlt die Kachel", "die Seite
weist den Creator ab"). Beide Aussagen sind jetzt umgekehrt und messen
zusaetzlich, was vorher niemand gemessen hat: dass die Creatorin auf
der Zahlen-Seite ihre EIGENEN Zahlen sieht und trotzdem keinen
einzigen Knopf zum Eintragen hat -- beides zusammen, denn "keine
Knoepfe" waere auch auf einer leeren Seite wahr. 56 -> 59.
Nicht von mir, nachgemessen gegen den Stand ohne diese Aenderungen:
pruef-struktur meldet dieselben 6 Fehler (crew-index/teamlage nicht
verlinkt, start.css 348 KB, totes CSS .nase, UTC-Datum).
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
+17
-127
@@ -47,7 +47,6 @@ import {
|
||||
db, protokolliere, echteIp, sitzungLesen, istLeitung,
|
||||
sichtbareCreatorIds, ROLLEN_SORTIERUNG, heuteLokal,
|
||||
} from "./workspace.js";
|
||||
import { kandidatenFinden, listeAmPfad, zuTagen } from "./workspace-tiktok-datei.js";
|
||||
|
||||
export const leistungRouter = express.Router();
|
||||
|
||||
@@ -870,137 +869,28 @@ leistungRouter.post("/workspace/api/leistung/netzwerk-import", gleicheHerkunft,
|
||||
});
|
||||
|
||||
/* =====================================================================
|
||||
DIE EIGENE TIKTOK-DATEI EINES CREATORS (11.09.2026)
|
||||
DER WEG UEBER DIE TIKTOK-DATEI IST ENTFERNT (11.09.2026)
|
||||
|
||||
Der letzte verbliebene Weg aus dem Plan vom 10.09.: Login Kit und
|
||||
Datenportabilitäts-API hängen beide an einem TikTok-Entwicklerkonto,
|
||||
und das wird es nicht geben ("hab ich nicht und werd ich nicht
|
||||
bekommen"). Dieser hier braucht keines -- der Creator lädt seine
|
||||
eigenen Daten bei TikTok herunter und gibt die Datei her.
|
||||
Gebaut am 11.09. vormittags, am selben Tag wieder ausgebaut. Filipe,
|
||||
mit den drei Knoepfen im Bild: *"ich will nur dass wir manager
|
||||
scouts, dogfather oder spicy sachen eintragen koennen und nicht die
|
||||
creator. ich will keine daten von denen kriegen, nur wir."*
|
||||
|
||||
Das Suchen und Umrechnen steht in workspace-tiktok-datei.js; hier
|
||||
stehen nur die beiden Wege und die Rechte.
|
||||
Der Weg war technisch einwandfrei -- und er war der einzige, bei dem
|
||||
ein CREATOR uns etwas gibt: seine eigene Datenkopie aus der
|
||||
TikTok-App. Genau das soll nicht sein. Es bleiben die beiden
|
||||
Wir-Wege: die eigene Datei und die Backstage-Tabelle der Agentur.
|
||||
|
||||
DIE DATEI WIRD NICHT GESPEICHERT. Sie wird gelesen, ausgewertet und
|
||||
fällt danach weg. In ihr stehen auch Direktnachrichten und der
|
||||
Ansehverlauf -- das ist nichts, was auf einem Server liegen soll,
|
||||
der es nicht braucht.
|
||||
VOLLSTAENDIG ENTFERNT, nicht nur versteckt: Schnittstellen, Leser
|
||||
(workspace-tiktok-datei.js), Knopf, Fenster und der fertige Text an
|
||||
den Creator. Ein Weg, der nur unsichtbar ist, ist weiterhin da --
|
||||
wer die Adresse kennt, benutzt ihn. Und ein Text, der einen Creator
|
||||
um seine Daten bittet, soll in diesem Haus nirgends mehr stehen.
|
||||
|
||||
WAS WIR DAMIT NICHT MEHR WISSEN: nichts, was Backstage nicht auch
|
||||
sagt. Die Datei war die zweite Quelle (COALESCE), nie die erste.
|
||||
===================================================================== */
|
||||
leistungRouter.post("/workspace/api/leistung/:creatorId/tiktok-datei/vorschau",
|
||||
gleicheHerkunft, express.json({ limit: "60mb" }), (req, res) => {
|
||||
try {
|
||||
const creatorId = Number(req.params.creatorId);
|
||||
if (!Number.isInteger(creatorId)) return res.status(400).json({ fehler: "ungueltig" });
|
||||
if (!darfEintragen(req.person)) return res.status(403).json({ fehler: "nicht_erlaubt" });
|
||||
if (!darfSehen(req.person, creatorId)) return res.status(404).json({ fehler: "nicht_gefunden" });
|
||||
|
||||
const inhalt = req.body?.inhalt;
|
||||
if (!inhalt || typeof inhalt !== "object") {
|
||||
return res.status(400).json({ fehler: "Das ist keine gelesene JSON-Datei." });
|
||||
}
|
||||
const kandidaten = kandidatenFinden(inhalt);
|
||||
if (!kandidaten.length) {
|
||||
return res.status(400).json({
|
||||
fehler: "In dieser Datei steht keine Liste mit Datumsangaben. "
|
||||
+ "Wurde beim Herunterladen wirklich JSON gewählt (nicht TXT) und "
|
||||
+ "„Alles auswählen“ angehakt?",
|
||||
});
|
||||
}
|
||||
/* Zu jedem Vorschlag gleich zeigen, was dabei herauskäme -- sonst
|
||||
muss der Mensch aus Schlüsselnamen raten, welcher der richtige
|
||||
ist. */
|
||||
const mitVorschau = kandidaten.map((k) => {
|
||||
const { tage } = zuTagen(k.beispiele.length ? listeAmPfad(inhalt, k.pfad) || [] : [], k.vorschlag);
|
||||
return {
|
||||
...k,
|
||||
tage_gesamt: tage.length,
|
||||
tage_beispiel: tage.slice(-3),
|
||||
/* Die Beispielzeilen gekürzt: In einem Vollarchiv hängt an
|
||||
einem Eintrag manchmal ein ganzer Kommentartext. */
|
||||
beispiele: k.beispiele.map((b) => {
|
||||
const klein = {};
|
||||
for (const [s, w] of Object.entries(b)) klein[s] = String(w ?? "").slice(0, 80);
|
||||
return klein;
|
||||
}),
|
||||
};
|
||||
});
|
||||
res.json({ kandidaten: mitVorschau });
|
||||
} catch (fehler) {
|
||||
console.error("[leistung] TikTok-Datei Vorschau:", fehler?.message);
|
||||
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||
}
|
||||
});
|
||||
|
||||
leistungRouter.post("/workspace/api/leistung/:creatorId/tiktok-datei",
|
||||
gleicheHerkunft, express.json({ limit: "60mb" }), (req, res) => {
|
||||
try {
|
||||
const creatorId = Number(req.params.creatorId);
|
||||
if (!Number.isInteger(creatorId)) return res.status(400).json({ fehler: "ungueltig" });
|
||||
if (!darfEintragen(req.person)) return res.status(403).json({ fehler: "nicht_erlaubt" });
|
||||
if (!darfSehen(req.person, creatorId)) return res.status(404).json({ fehler: "nicht_gefunden" });
|
||||
|
||||
const inhalt = req.body?.inhalt;
|
||||
const pfad = String(req.body?.pfad || "");
|
||||
const zuordnung = req.body?.zuordnung;
|
||||
if (!inhalt || !pfad || !zuordnung?.tag) {
|
||||
return res.status(400).json({ fehler: "Es fehlt die Auswahl, was gelesen werden soll." });
|
||||
}
|
||||
const liste = listeAmPfad(inhalt, pfad);
|
||||
if (!liste) return res.status(400).json({ fehler: "Diese Liste gibt es in der Datei nicht." });
|
||||
|
||||
const { tage, uebersprungen } = zuTagen(liste, zuordnung);
|
||||
const heute = heuteLokal();
|
||||
const brauchbar = tage.filter((t) => t.tag <= heute
|
||||
/* Ein Tag ohne eine einzige Zahl ist keine Messung. Dieselbe
|
||||
Regel wie beim Backstage-Import. */
|
||||
&& (t.dauer_min !== null || t.diamanten !== null || t.zuschauer_max !== null));
|
||||
if (!brauchbar.length) return res.status(400).json({ fehler: "keine_brauchbaren_tage" });
|
||||
|
||||
const d = db();
|
||||
const schreiben = d.prepare(`
|
||||
INSERT INTO leistung
|
||||
(creator_id, tag, diamanten, dauer_min, gueltiger_tag, zuschauer_max,
|
||||
erfasst, erfasst_von, quelle)
|
||||
VALUES (?,?,?,?,?,?,?,?,'import')
|
||||
ON CONFLICT(creator_id, tag) DO UPDATE SET
|
||||
/* NUR FÜLLEN, NICHT ÜBERSCHREIBEN.
|
||||
|
||||
Anders als beim Backstage-Import, der die Wahrheit der
|
||||
Agentur bringt: Diese Datei kommt vom Creator und ist eine
|
||||
ZWEITE Quelle. Wo schon eine Zahl steht -- von Hand
|
||||
eingetragen oder aus Backstage --, bleibt sie stehen.
|
||||
Andersherum würde ein Dateiupload stillschweigend die
|
||||
offiziellen Zahlen ersetzen, und niemand wüsste hinterher,
|
||||
welche gilt. */
|
||||
diamanten = COALESCE(leistung.diamanten, excluded.diamanten),
|
||||
dauer_min = COALESCE(leistung.dauer_min, excluded.dauer_min),
|
||||
zuschauer_max = COALESCE(leistung.zuschauer_max, excluded.zuschauer_max),
|
||||
gueltiger_tag = MAX(leistung.gueltiger_tag, excluded.gueltiger_tag)`);
|
||||
|
||||
let geschrieben = 0, ergaenzt = 0;
|
||||
const vorhanden = d.prepare("SELECT 1 FROM leistung WHERE creator_id = ? AND tag = ?");
|
||||
d.exec("BEGIN");
|
||||
try {
|
||||
for (const t of brauchbar) {
|
||||
const gabEs = !!vorhanden.get(creatorId, t.tag);
|
||||
schreiben.run(creatorId, t.tag, t.diamanten, t.dauer_min,
|
||||
(t.dauer_min ?? 0) > 0 ? 1 : 0, t.zuschauer_max,
|
||||
new Date().toISOString(), req.person.id);
|
||||
if (gabEs) ergaenzt++; else geschrieben++;
|
||||
}
|
||||
d.exec("COMMIT");
|
||||
} catch (f) { d.exec("ROLLBACK"); throw f; }
|
||||
|
||||
protokolliere("leistung_tiktok_datei", {
|
||||
personId: req.person.id, rolle: req.person.rolle, ip: echteIp(req),
|
||||
detail: `Creator #${creatorId}: ${geschrieben} neu, ${ergaenzt} ergaenzt`.slice(0, 120),
|
||||
});
|
||||
res.json({ geschrieben, ergaenzt, uebersprungen: uebersprungen.length });
|
||||
} catch (fehler) {
|
||||
console.error("[leistung] TikTok-Datei:", fehler?.message);
|
||||
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||
}
|
||||
});
|
||||
|
||||
/** Vorschau: Was WÜRDE passieren? Schreibt nichts. */
|
||||
leistungRouter.post("/workspace/api/leistung/:creatorId/import/vorschau", gleicheHerkunft,
|
||||
|
||||
Reference in New Issue
Block a user