Filipe: "damit meine videos auch da auf der app rein kommen ... sobald
ich ein video poste erscheint es sofort in der app fuer die ganze
community ... dass man das Coverbild und den Text sieht ... fuer meinen
Account, dann DogFather Clips und HasiDog."
Der Weg, der HEUTE funktioniert -- ohne Freigabe, ohne Geheimnis, ohne
Wartezeit: Adresse einfuegen, alles andere geht von allein.
Link -> oEmbed (Titel, Cover-Adresse, Account)
-> Cover HERUNTERLADEN und bei uns ablegen
-> Eintrag mit Bild, Text und Knopf zum Video
DAS COVER WIRD KOPIERT, NICHT VERLINKT -- der wichtigste Satz.
TikToks Bildadresse ist signiert und laeuft ab. Heute an einem echten
Video nachgemessen: x-expires = 1789812000, also in 48 Stunden. Wer sie
nur speichert, hat uebermorgen schwarze Kacheln. Beim Bauen merkt man
das nicht und beim Testen auch nicht -- es faellt erst am uebernaechsten
Tag auf, und dann sieht die ganze App kaputt aus.
Deshalb wandert das Bild in dieselbe Ablage wie jeder Anhang und geht
durch dieselbe Bytepruefung. Ein heruntergeladenes Cover ist eine
FREMDE Datei; dass der Typ hier von einem fremden Server behauptet wird
statt vom eigenen Browser, macht ihn nicht glaubwuerdiger.
NUR SEINE EIGENEN KANAELE. Der Account aus der Antwort wird gegen
KANAELE geprueft (kanalVonHandle). Genommen wird author_url (.../@name),
nicht author_name -- der Anzeigename aendert sich, wenn jemand ihn
umstellt. Ein fremdes Video in Filipes Highlights waere nicht bloss
falsch einsortiert, es waere fremder Inhalt unter seinem Namen: 403.
DIE PRUEFUNG SCHALTET TIKTOK AB (server/pruef-video.mjs, 37 Pruefungen)
Ein nachgebauter Dienst auf 127.0.0.1 antwortet wie TikTok, mitsamt
Ablaufstempel. Im letzten Abschnitt wird er ABGESCHALTET. Danach muss
die alte Cover-Adresse ins Leere laufen und unsere weiterhin ein Bild
liefern -- beides wird gemessen, nebeneinander. Waere das Bild nur
verlinkt, waeren beide tot, genau wie uebermorgen im Betrieb.
Die Adresse des Dienstes kommt aus TIKTOK_OEMBED_BASIS. Steht sie nicht
da, gilt TikTok -- kein Verhalten, das sich still aendert. Eine
Pruefung, die das echte TikTok braucht, misst fremde Verfuegbarkeit
statt unseren Code und wird irgendwann rot, ohne dass etwas kaputt ist.
VIER GEGENPROBEN, weil 37 von 37 im ersten Lauf kein Beweis ist:
a) Cover nicht mehr kopieren -> 9 Pruefungen rot
b) author_name statt author_url -> 22 rot
c) Bytepruefung entfernen -> 2 rot (genau Abschnitt 5)
d) Dublettenpruefung entfernen -> 4 rot (genau Abschnitt 4)
Jede schlaegt dort an, wo sie soll. Und eine fuenfte Gegenprobe ist ins
Leere gelaufen: Der Patch lief ueber python3, das es hier nicht gibt --
die Datei blieb unveraendert und der Lauf war gruen. Haette ich die
Ausgabe nicht gelesen, haette ich behauptet, die Pruefung koenne rot
werden, ohne sie je rot gesehen zu haben. Der dritte Ausgang, an mir
selbst.
DAZU:
- eintraege.quelle_url / quelle_kanal / quelle_geholt_am (Umstellung)
- KANAELE bekommt handle, dazu kanalVonHandle()
- videoRouter steht VOR bereicheRouter, sonst schluckt /:bereich ihn
- Eingabefeld und Kanal-Knopf in bereich.html/.js, Farben wie bei den
Aufgaben-Kanaelen
- Stempel 202609171249
Nicht darin: die Kanal-Filterzeile in der Galerie, die Handy-Verknuepfung
(Teilen -> Workspace) und der Zustand "nicht mehr da" fuer geloeschte
Videos. Stufe B (Display API) braucht Filipes Entwickler-Freigabe.
Co-Authored-By: Claude Opus 5 <[email protected]>
118 lines
5.5 KiB
HTML
118 lines
5.5 KiB
HTML
<!doctype html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||
<title>Dateien · Spicy & Dogi</title>
|
||
<meta name="robots" content="noindex, nofollow" />
|
||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||
<!-- Die Farbe der Fensterleiste, wenn der Workspace als App laeuft.
|
||
Stand auf #0674b9 (kraeftiges Blau) und stach damit als einziger
|
||
heller Balken ueber einer durchweg dunklen Seite. Jetzt derselbe
|
||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||
eine Flaeche sind statt zweier. -->
|
||
<meta name="theme-color" content="#06090f" />
|
||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609171249" />
|
||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609171249" />
|
||
<link rel="stylesheet" href="assets/css/gate.css?v=202609171249" />
|
||
<link rel="stylesheet" href="assets/css/start.css?v=202609171249" />
|
||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609171249" />
|
||
<link rel="stylesheet" href="assets/css/dateien.css?v=202609171249" />
|
||
<link rel="stylesheet" href="assets/css/module.css?v=202609171249" />
|
||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||
ohne Umfaerben im Browser, ohne Flackern. -->
|
||
<link rel="stylesheet" href="assets/css/haus.css?v=202609171249" />
|
||
</head>
|
||
|
||
<body class="start">
|
||
|
||
<!-- Der Schleier ueber der Buehne (Casper und HasiDog in den unteren
|
||
Ecken, siehe start.css). Ein eigenes Element statt eines dritten
|
||
Pseudo-Elements -- body hat nur ::before und ::after. -->
|
||
<div class="schleier" aria-hidden="true"></div>
|
||
|
||
<header class="kopfleiste">
|
||
<button type="button" class="zurueck-knopf" id="zurueck" hidden>
|
||
<svg class="zurueck-knopf__pfeil" viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="M14.5 5.5 8 12l6.5 6.5" />
|
||
</svg>
|
||
<span class="zurueck-knopf__text">Zurück</span>
|
||
</button>
|
||
<p class="marke"><span class="marke__text"><a class="zurueck" href="start.html">Creator Workspace</a> · Dateien</span></p>
|
||
<div class="kopfleiste__rechts">
|
||
<span class="wer" id="wer">…</span>
|
||
<button type="button" class="abmelden" id="abmelden">Abmelden</button>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="inhalt inhalt--breit">
|
||
|
||
<section class="kopf-zeile">
|
||
<div>
|
||
<p class="marke">Ablage</p>
|
||
<h1 class="titel">Dateien & Freigaben</h1>
|
||
<p class="unterzeile">Entwurf → Review → Freigabe. Die aktuelle Version ist immer klar erkennbar.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Hinweis für alle, die nicht ablegen dürfen (Creator). Steht statt
|
||
des Ablegefeldes, damit klar ist warum -- ein einfach fehlendes
|
||
Feld wirkt wie ein Fehler. -->
|
||
<p class="nur-lesen" id="nur-lesen" hidden>
|
||
Hier siehst du die Dateien deines Bereichs. <strong>Abgelegt werden sie
|
||
von DogFather oder von Scouts</strong> – du kannst sie öffnen, aber nichts hochladen.
|
||
</p>
|
||
|
||
<!-- Ablegefeld. Klick öffnet die Dateiauswahl, Ziehen funktioniert
|
||
ebenso -- beides landet im selben Ablauf. -->
|
||
<div class="ablage" id="ablage" tabindex="0" role="button"
|
||
aria-label="Datei auswählen oder hierher ziehen">
|
||
<svg class="ablage__zeichen" viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="M12 16V4m0 0L7.5 8.5M12 4l4.5 4.5" />
|
||
<path d="M4 15v3.5A1.5 1.5 0 0 0 5.5 20h13a1.5 1.5 0 0 0 1.5-1.5V15" />
|
||
</svg>
|
||
<p class="ablage__text">Datei hierher ziehen oder <strong>auswählen</strong></p>
|
||
<p class="ablage__klein" id="ablage-grenze">bis 25 MB</p>
|
||
<input type="file" id="feld-datei" hidden />
|
||
</div>
|
||
|
||
<div class="hochlade-zeile" id="zuordnung" hidden>
|
||
<div class="feld feld--breit">
|
||
<label class="feld-schild" for="f-creator">Ablegen im Bereich von <span class="leise">(optional)</span></label>
|
||
<select id="f-creator"><option value="">— kein Bereich —</option></select>
|
||
</div>
|
||
<!-- Wer die Datei sehen darf. Mehrfachauswahl: dieselbe Datei kann
|
||
an mehrere Personen gehen, ohne sie mehrfach hochzuladen. -->
|
||
<div class="feld feld--breit">
|
||
<label class="feld-schild">Wer darf sie sehen?</label>
|
||
<p class="leise" id="wahl-hinweis">Niemand ausgewählt – dann sieht sie nur DogFather.</p>
|
||
<div class="wahl" id="wahl"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<p class="fortschritt" id="fortschritt" hidden><span id="fortschritt-text"></span></p>
|
||
<p class="fehler" id="fehler" role="alert" aria-live="polite"></p>
|
||
|
||
<div class="filter" id="filter">
|
||
<button type="button" class="schritt" data-status="" aria-pressed="true">Alle</button>
|
||
<button type="button" class="schritt" data-status="entwurf" aria-pressed="false">Entwurf</button>
|
||
<button type="button" class="schritt" data-status="review" aria-pressed="false">Review</button>
|
||
<button type="button" class="schritt" data-status="freigegeben" aria-pressed="false">Freigegeben</button>
|
||
</div>
|
||
|
||
<div id="liste" aria-busy="true"><p class="leise">Dateien werden geladen …</p></div>
|
||
|
||
</main>
|
||
|
||
<script src="assets/js/wahl.js?v=202609171249" defer></script>
|
||
<script src="assets/js/bereiche.js?v=202609171249" defer></script>
|
||
<script src="assets/js/kopf.js?v=202609171249" defer></script>
|
||
<script src="assets/js/glocke.js?v=202609171249" defer></script>
|
||
<script src="assets/js/dateien.js?v=202609171249" defer></script>
|
||
</body>
|
||
</html>
|