From d766be57b67c3a3695d268d87dec77571395aebc Mon Sep 17 00:00:00 2001 From: Dogfather Date: Sat, 19 Sep 2026 00:32:57 +0200 Subject: [PATCH] Anruf: wer auflegt, hinterlaesst jetzt auch eine Spur MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Filipe, 00:30 Uhr: „hab angerufen aufgelegt und da steht immer noch nichts im chat vom anruf...." Im Protokoll: vier Anrufe, je drei bis zehn Sekunden, kein einziger Eintrag im Gespraech. Und mein Denkfehler dahinter war einfach: „Verpasster Anruf" stand NUR in `aufraeumen()` -- also erst, wenn ein Anruf nach zwei Minuten von selbst verfaellt. Wer vorher auflegt, loeschte ihn spurlos. Abschnitt 5e hat damit genau den Weg geprueft, den niemand geht: warten, bis es von allein aufhoert. Im Alltag legt man auf. Fuer die andere Seite ist ein Anrufer, der aufgibt, ERST RECHT ein verpasster Anruf. UND EINE ZWEITE FALLE, die die erste verdeckt hat: `verpasstVermerken` nahm den Anrufer aus der Runde der Anwesenden (`a.wer`). Beim Verfallen steht er noch darin -- beim AUFLEGEN ist sie leer. Die Zeile waere also auch dann ausgefallen, wenn der Aufruf an der richtigen Stelle gestanden haette. Jetzt kommt er aus `a.anrufer`, wie beim gefuehrten Anruf auch. Zwei Fehler, die einander gedeckt haben, und beide hat dieselbe Pruefluecke durchgelassen: Ich hatte den Ablauf geprueft, den ich gebaut hatte, nicht den, den ein Mensch geht. Geprueft: pruef-anruf 106 -> 111. Der neue Abschnitt ruft an, wartet kurz, legt auf -- und misst, dass genau EINE Zeile entsteht, dass sie „verpasst" sagt, dass der Anrufer daran steht und dass spaeteres Aufraeumen keine zweite schreibt. Co-Authored-By: Claude Opus 5 --- server/pruef-anruf.mjs | 61 +++++++++++++++++++++++++++++++++++++++ server/workspace-anruf.js | 42 +++++++++++++++++++++------ 2 files changed, 94 insertions(+), 9 deletions(-) diff --git a/server/pruef-anruf.mjs b/server/pruef-anruf.mjs index 63780a22..47c04f29 100644 --- a/server/pruef-anruf.mjs +++ b/server/pruef-anruf.mjs @@ -302,6 +302,67 @@ melde("=== 5. Auflegen ==="); telefoniert?". Drei Minuten sind ein Gespraech, zwoelf Sekunden sind ein Verwaehlen. ======================================================================= */ +/* ======================================================================= + 5g. WENN DER ANRUFER AUFLEGT, BEVOR JEMAND RANGEHT + + Filipe, 00:30 Uhr: „hab angerufen aufgelegt und da steht immer noch + nichts im chat vom anruf...." + + Vier Anrufe im Protokoll, je drei bis zehn Sekunden, kein einziger + Eintrag im Gespraech. Und mein Denkfehler dahinter: + + „Verpasster Anruf" stand NUR in `aufraeumen()` -- also erst, wenn + ein Anruf nach zwei Minuten von selbst verfaellt. Wer vorher + auflegt, loeschte ihn spurlos. Abschnitt 5e hat genau den Weg + geprueft, den niemand geht: warten, bis es von allein aufhoert. + Im Alltag legt man auf. + + Dazu kam eine zweite Falle: `verpasstVermerken` nahm den Anrufer + aus der Runde der Anwesenden. Beim Verfallen steht er noch darin -- + beim Auflegen ist sie leer. Die Zeile waere also auch dann + ausgefallen, wenn der Aufruf an der richtigen Stelle gestanden + haette. Zwei Fehler, die einander verdeckt haben. + ======================================================================= */ +melde(""); +melde("=== 5g. Anrufer legt auf, bevor jemand rangeht ==="); +{ + const raum = json(await roh("/workspace/api/chat/raeume", HAUS, + { cookie: kDogi })).raeume?.[0]; + if (!raum) { + unklar("kein Gespraech vorhanden -- nicht nachgesehen"); + } else { + const vorher = (json(await roh(`/workspace/api/chat/raeume/${raum.id}/nachrichten`, HAUS, + { cookie: kDogi })).nachrichten || []).length; + + await roh(`/workspace/api/anruf/${raum.id}/start`, HAUS, { cookie: kDogi }, { video: false }); + /* Kurz warten wie im echten Leben -- und auflegen, ohne dass + jemand rangegangen ist. */ + await new Promise((r) => setTimeout(r, 800)); + const ende = await roh(`/workspace/api/anruf/${raum.id}/ende`, HAUS, { cookie: kDogi }, {}); + ok(ende.code === 200, `aufgelegt (${ende.code})`); + + const nachher = json(await roh(`/workspace/api/chat/raeume/${raum.id}/nachrichten`, HAUS, + { cookie: kDogi })).nachrichten || []; + ok(nachher.length === vorher + 1, + `es steht trotzdem eine Zeile im Gespraech (${vorher} -> ${nachher.length})`); + + const letzte = nachher[nachher.length - 1]; + ok(/[Vv]erpasst/.test(letzte?.text || ""), + `und sie sagt „verpasst" („${letzte?.text}")`); + ok(letzte?.von_id !== undefined && letzte?.von, + `mit dem Anrufer daran (${letzte?.von})`); + + /* UND NICHT ZWEIMAL: `aufraeumen()` darf nicht spaeter noch eine + zweite Zeile schreiben -- der Anruf ist ja schon geloescht. */ + await new Promise((r) => setTimeout(r, 300)); + await roh("/workspace/api/anruf/offen", CREW, { cookie: kHand }); + const nochmal = (json(await roh(`/workspace/api/chat/raeume/${raum.id}/nachrichten`, HAUS, + { cookie: kDogi })).nachrichten || []).length; + ok(nochmal === nachher.length, + `und bleibt bei einer (${nochmal})`); + } +} + melde(""); melde("=== 5f. Ein gefuehrter Anruf ==="); { diff --git a/server/workspace-anruf.js b/server/workspace-anruf.js index 76bc18ec..648e209c 100644 --- a/server/workspace-anruf.js +++ b/server/workspace-anruf.js @@ -210,9 +210,16 @@ function anrufVermerken(raumId, a) { * richtigen Stelle im Verlauf, wird mitgezaehlt wie jede andere und * braucht keine Sonderbehandlung in der Oberflaeche. */ function verpasstVermerken(raumId, a) { - const anrufer = [...a.wer.entries()][0]; - if (!anrufer) return; - const [id, wer] = anrufer; + /* AUS `a.anrufer`, NICHT AUS `a.wer`. + + `wer` ist die Runde der gerade Anwesenden. Beim Verfallen steht + der Anrufer noch darin -- beim AUFLEGEN ist sie leer, und die + Zeile waere still ausgefallen. Genau dieser Unterschied hat den + Fehler vom 19.09. so schwer sichtbar gemacht: In der Pruefung + (Anruf verfaellt) ging es, im Alltag (Anrufer legt auf) nicht. */ + const wer = a.anrufer; + if (!wer) return; + const id = wer.id; const d = db(); const n = new Date().toISOString(); const text = a.video ? "📞 Verpasster Videoanruf" : "📞 Verpasster Anruf"; @@ -471,14 +478,31 @@ anrufRouter.post("/workspace/api/anruf/:raum/ende", gleicheHerkunft, (req, res) const dauer = war ? Math.round((Date.now() - war.seit) / 1000) : 0; if (!a.wer.size) { laufend.delete(raumId); - /* DER LETZTE GEHT -- also ist das Gespraech vorbei. Jetzt - gehoert eine Zeile in den Chat, wie bei jedem Telefon. + /* DER LETZTE GEHT -- also ist es vorbei. Jetzt gehoert eine + Zeile in den Chat, wie bei jedem Telefon. + + ZWEI FAELLE, UND DER ZWEITE HAT GEFEHLT (19.09.2026): + + warGespraech jemand ist rangegangen -> „Anruf · 0:42" + sonst niemand ist rangegangen -> „Verpasster Anruf" + + Der zweite Fall stand vorher NUR in `aufraeumen()` -- also + erst, wenn ein Anruf nach zwei Minuten von selbst verfaellt. + Wer vorher auflegt, loeschte ihn damit spurlos. + + Genau das hat Filipe gemeldet: viermal angerufen, nach drei + bis zehn Sekunden aufgelegt, „da steht immer noch nichts im + chat vom anruf". Vier verpasste Anrufe, von denen keiner + irgendwo stand -- und fuer die andere Seite ist ein Anrufer, + der aufgibt, ERST RECHT ein verpasster Anruf. + Eigenes try: Ein Fehler beim Schreiben darf das Auflegen nicht scheitern lassen. */ - if (warGespraech) { - try { anrufVermerken(raumId, a); } catch (fe) { - console.error("[anruf] vermerken:", fe?.message); - } + try { + if (warGespraech) anrufVermerken(raumId, a); + else verpasstVermerken(raumId, a); + } catch (fe) { + console.error("[anruf] vermerken:", fe?.message); } } chatEreignis(raumId, {