Fotoposts von TikTok kommen jetzt an -- das war die Ursache
GEFUNDEN HAT ES DAS PROTOKOLL, das eine halbe Stunde vorher dazukam. Filipes Versuche standen Minuten spaeter als `video_gescheitert` da, mit Grund: highlight .../@dogfather0804/photo/7693113561568136470 -- 400 highlight https://vm.tiktok.com/ZN8kdxP9N/ -- 400 Am echten Konto nachgemessen: .../photo/7693113561568136470 -> 400 "Something went wrong" .../video/7693113561568136470 -> 200, mit Titel vm.tiktok.com/ZN8kdxP9N/ -> leitet auf die /photo/-Adresse TikToks Auskunft kennt FOTOPOSTS (Slideshows) nicht -- dieselbe Nummer unter /video/ aber schon. Filipe postet seit kurzem solche Beitraege. Deshalb "es ging doch immer bis jetzt": Es lag weder an einer Auslieferung noch am Haus, sondern an der Art des Posts. Der Server war die ganze Zeit unveraendert (ein Neustart seit 04.10.), und genau das hat die Suche in die falsche Richtung geschickt. Jetzt wird bei einem Fehlschlag ein zweites Mal gefragt: erst den Kurzlink aufloesen -- er verraet von aussen nicht, was dahinter steckt --, dann /photo/ auf /video/ drehen. Aufgeloest wird nur ueber den Ort-Kopf (`redirect: "manual"`), die Seite selbst wird nie geholt; sie ist ein Megabyte gross und enthaelt nichts, was wir brauchen. NUR BEIM FEHLSCHLAG: Ein gewoehnliches Video kostet keine einzige zusaetzliche Anfrage. Gemessen: Video 204 ms wie bisher, Fotopost 676 ms, Kurzlink auf Fotopost 827 ms -- alle drei mit Titel und Vorschaubild. Gegengemessen an genau den zwei Adressen, die bei ihm gescheitert sind: beide liefern jetzt Titel und Bild. pruef-video 74, pruef-teilen 27 -- 0 Fehler. WAS ICH DARAUS MITNEHME: Ich habe heute stundenlang von aussen ausgeschlossen, was es NICHT ist -- Adresse, Haus, Sitzung, Manifest, Service Worker, Zwischenspeicher. Beantwortet hat die Frage am Ende eine einzige Protokollzeile. Die haette am Anfang stehen muessen, nicht nach der halben Suche. Dieselbe Lehre wie am 06.09. im Shop, und ich habe sie heute zweimal gebraucht. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -140,14 +140,81 @@ async function holeMitFrist(adresse, kopf = {}) {
|
||||
const OEMBED_BASIS = process.env.TIKTOK_OEMBED_BASIS || "https://www.tiktok.com/oembed";
|
||||
|
||||
/** Die Auskunft zu einem Video: Titel, Cover-Adresse, Account. */
|
||||
export async function videoAuskunft(url) {
|
||||
/** Wohin fuehrt ein Kurzlink wirklich -- ohne die Seite zu laden.
|
||||
*
|
||||
* `vm.tiktok.com/ZN8kdxP9N/` verraet von aussen nicht, ob dahinter
|
||||
* ein Video oder ein Fotopost steckt. Nur die Weiterleitung sagt es.
|
||||
* Gelesen wird deshalb NUR der Ort-Kopf (`redirect: "manual"`); die
|
||||
* Seite selbst wird nie geholt -- sie ist ein Megabyte gross und
|
||||
* enthaelt nichts, was wir brauchen. */
|
||||
async function endgueltigeAdresse(url) {
|
||||
let jetzt = String(url);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const abbruch = new AbortController();
|
||||
const uhr = setTimeout(() => abbruch.abort(), FRIST_MS);
|
||||
let a;
|
||||
try {
|
||||
a = await fetch(jetzt, { method: "GET", redirect: "manual", signal: abbruch.signal });
|
||||
} catch { return jetzt; } finally { clearTimeout(uhr); }
|
||||
/* Den Koerper wegwerfen, nicht lesen -- sonst bleibt die
|
||||
Verbindung offen und wir laden die ganze Seite umsonst. */
|
||||
try { await a.body?.cancel(); } catch { /* egal */ }
|
||||
const ort = a.headers.get("location");
|
||||
if (!ort) return jetzt;
|
||||
try { jetzt = new URL(ort, jetzt).toString(); } catch { return jetzt; }
|
||||
}
|
||||
return jetzt;
|
||||
}
|
||||
|
||||
/** Ein Fotopost unter derselben Nummer als Video angefragt.
|
||||
*
|
||||
* WARUM DAS NOETIG IST (05.10.2026, gemessen am echten Konto):
|
||||
*
|
||||
* .../photo/7693113561568136470 -> 400 "Something went wrong"
|
||||
* .../video/7693113561568136470 -> 200 mit Titel
|
||||
*
|
||||
* TikToks Auskunft kennt Fotoposts (Slideshows) nicht, dieselbe
|
||||
* Nummer unter /video/ aber schon. Filipe postet seit kurzem solche
|
||||
* Beitraege -- deshalb "es ging doch immer bis jetzt": Es lag weder
|
||||
* an einer Auslieferung noch am Haus, sondern an der Art des Posts.
|
||||
*
|
||||
* Gibt es nichts zu drehen, kommt `null` zurueck -- dann bleibt es
|
||||
* bei der ersten Antwort und ihrer Fehlermeldung. */
|
||||
function alsVideoFassung(url) {
|
||||
try {
|
||||
const u = new URL(String(url));
|
||||
if (!/\/photo\/\d+/.test(u.pathname)) return null;
|
||||
u.pathname = u.pathname.replace("/photo/", "/video/");
|
||||
return u.toString();
|
||||
} catch { return null; }
|
||||
}
|
||||
|
||||
async function auskunftHolen(url) {
|
||||
const a = await holeMitFrist(
|
||||
`${OEMBED_BASIS}?url=${encodeURIComponent(url)}`,
|
||||
{ accept: "application/json" });
|
||||
if (!a.ok) return { fehler: `TikTok antwortet nicht (${a.status}).` };
|
||||
if (!a.ok) return { status: a.status, daten: null };
|
||||
let j = null;
|
||||
try { j = JSON.parse(a.text()); } catch { j = null; }
|
||||
if (!j || !j.title) return { fehler: "TikTok hat nichts zu diesem Video geschickt." };
|
||||
return { status: a.status, daten: j };
|
||||
}
|
||||
|
||||
export async function videoAuskunft(url) {
|
||||
let versuch = await auskunftHolen(url);
|
||||
|
||||
/* ZWEITER ANLAUF FUER FOTOPOSTS. Nur wenn der erste scheitert --
|
||||
bei einem gewoehnlichen Video kostet das keine einzige zusaetzliche
|
||||
Anfrage. Erst den Kurzlink aufloesen (er verraet von aussen nicht,
|
||||
was dahinter steckt), dann /photo/ auf /video/ drehen. */
|
||||
if (!versuch.daten) {
|
||||
const echt = await endgueltigeAdresse(url);
|
||||
const gedreht = alsVideoFassung(echt);
|
||||
if (gedreht) versuch = await auskunftHolen(gedreht);
|
||||
}
|
||||
|
||||
const j = versuch.daten;
|
||||
if (!j) return { fehler: `TikTok antwortet nicht (${versuch.status}).` };
|
||||
if (!j.title) return { fehler: "TikTok hat nichts zu diesem Video geschickt." };
|
||||
/* Der Account steht in `author_url` (…/@name). `author_name` ist der
|
||||
ANZEIGENAME und aendert sich, wenn jemand ihn umstellt -- als
|
||||
Schluessel waere er die falsche Wahl. */
|
||||
|
||||
Reference in New Issue
Block a user