diff --git a/package-lock.json b/package-lock.json index 5dc45cf..2c00890 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "license": "MIT", "dependencies": { - "@discordjs/voice": "^0.18.0", + "@discordjs/voice": "^0.19.2", "@fastify/cookie": "^11.1.2", "@fastify/multipart": "^10.1.0", "@fastify/static": "^10.1.2", @@ -121,30 +121,25 @@ } }, "node_modules/@discordjs/voice": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.18.0.tgz", - "integrity": "sha512-BvX6+VJE5/vhD9azV9vrZEt9hL1G+GlOdsQaVl5iv9n87fkXjf3cSwllhR3GdaUC8m6dqT8umXIWtn3yCu4afg==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.19.2.tgz", + "integrity": "sha512-3yJ255e4ag3wfZu/DSxeOZK1UtnqNxnspmLaQetGT0pDkThNZoHs+Zg6dgZZ19JEVomXygvfHn9lNpICZuYtEA==", "license": "Apache-2.0", "dependencies": { - "@types/ws": "^8.5.12", - "discord-api-types": "^0.37.103", + "@snazzah/davey": "^0.1.9", + "@types/ws": "^8.18.1", + "discord-api-types": "^0.38.41", "prism-media": "^1.3.5", - "tslib": "^2.6.3", - "ws": "^8.18.0" + "tslib": "^2.8.1", + "ws": "^8.19.0" }, "engines": { - "node": ">=18" + "node": ">=22.12.0" }, "funding": { "url": "https://github.com/discordjs/discord.js?sponsor" } }, - "node_modules/@discordjs/voice/node_modules/discord-api-types": { - "version": "0.37.120", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.120.tgz", - "integrity": "sha512-7xpNK0EiWjjDFp2nAhHXezE4OUWm7s1zhc/UXXN6hnFFU8dfoPHgV0Hx0RPiCa3ILRpdeh152icc68DGCyXYIw==", - "license": "MIT" - }, "node_modules/@discordjs/ws": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.2.3.tgz", @@ -180,6 +175,18 @@ "url": "https://github.com/discordjs/discord.js?sponsor" } }, + "node_modules/@emnapi/core": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.3.tgz", + "integrity": "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.3", + "tslib": "^2.4.0" + } + }, "node_modules/@emnapi/runtime": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", @@ -190,6 +197,17 @@ "tslib": "^2.4.0" } }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz", + "integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@fastify/accept-negotiator": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@fastify/accept-negotiator/-/accept-negotiator-2.0.1.tgz", @@ -1000,6 +1018,27 @@ "node": ">=8" } }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.3.tgz", + "integrity": "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + } + }, "node_modules/@nodable/entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.2.0.tgz", @@ -1063,6 +1102,270 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@snazzah/davey": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey/-/davey-0.1.12.tgz", + "integrity": "sha512-V+NlX5931RwVamZhhEfZekMdcvXDKdMAmHW1AuGaykVQsNyBOq3bpmGpoKRBDCYgFWKIufJ0Dcg3m4cYhvUy6g==", + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "funding": { + "url": "https://github.com/sponsors/Snazzah" + }, + "optionalDependencies": { + "@snazzah/davey-android-arm-eabi": "0.1.12", + "@snazzah/davey-android-arm64": "0.1.12", + "@snazzah/davey-darwin-arm64": "0.1.12", + "@snazzah/davey-darwin-x64": "0.1.12", + "@snazzah/davey-freebsd-x64": "0.1.12", + "@snazzah/davey-linux-arm-gnueabihf": "0.1.12", + "@snazzah/davey-linux-arm64-gnu": "0.1.12", + "@snazzah/davey-linux-arm64-musl": "0.1.12", + "@snazzah/davey-linux-x64-gnu": "0.1.12", + "@snazzah/davey-linux-x64-musl": "0.1.12", + "@snazzah/davey-wasm32-wasi": "0.1.12", + "@snazzah/davey-win32-arm64-msvc": "0.1.12", + "@snazzah/davey-win32-ia32-msvc": "0.1.12", + "@snazzah/davey-win32-x64-msvc": "0.1.12" + } + }, + "node_modules/@snazzah/davey-android-arm-eabi": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-android-arm-eabi/-/davey-android-arm-eabi-0.1.12.tgz", + "integrity": "sha512-6VC/an+Sx5dI5skb+90rYcIB1jhm48Rl0nDaw0UNT4bz1rMjpVfmmZqeocYXMq96IdbBMlE6OTKGcBm2C3gkQg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@snazzah/davey-android-arm64": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-android-arm64/-/davey-android-arm64-0.1.12.tgz", + "integrity": "sha512-0Bwd03/JsTFhlPhF4q/LW0RxSzntFpQdhz+TBdFljYSg8IEyA38saPJeTNjpIgDfhAumPzvhCdfS6O5qT8yXDw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@snazzah/davey-darwin-arm64": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-darwin-arm64/-/davey-darwin-arm64-0.1.12.tgz", + "integrity": "sha512-lKMV6ITi9BQLt0fx/pAT7M8xcojVK7bryVJGdaW3bq8gABFslS3ti/KzrWabQvhpEV71FZe5mV0UcKHFVaTsZw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@snazzah/davey-darwin-x64": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-darwin-x64/-/davey-darwin-x64-0.1.12.tgz", + "integrity": "sha512-vXXc/eW/e3TQeb7VsdtrPqs3/22j0aSqiP1ZXmZtDjQRBwgSxwItWYa6sh5MELP2EHB2igNlGzB6Hc0XlbGi4g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@snazzah/davey-freebsd-x64": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-freebsd-x64/-/davey-freebsd-x64-0.1.12.tgz", + "integrity": "sha512-G1gas5HrC4Xp3mRY0+OeAqXS6fG2tRgBEc8gQh69Hw4YK9RV9mzQKcmoKMkBM72U1+2C+2u57dolnKKzwozByQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@snazzah/davey-linux-arm-gnueabihf": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-linux-arm-gnueabihf/-/davey-linux-arm-gnueabihf-0.1.12.tgz", + "integrity": "sha512-97Fujh82r2Ll7dPZeNuoZ3yKfsqycf3c93OWXOo/ThNL/18Onl2Ht4SIvpX6VHhfeS9bDpHJ1lHCaz1b/i5ocw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@snazzah/davey-linux-arm64-gnu": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-linux-arm64-gnu/-/davey-linux-arm64-gnu-0.1.12.tgz", + "integrity": "sha512-FWyAOv52cHKDM4BOsmImKKogHFvqNFoXmZcicNJbX3XpVl8Mas88ZoXQ+IA5V+qc9pNtAl1MbWwEZ9JrqAQtbg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@snazzah/davey-linux-arm64-musl": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-linux-arm64-musl/-/davey-linux-arm64-musl-0.1.12.tgz", + "integrity": "sha512-ptRbLSQxtV6EjXppS5z7qaPDI0NRKhrkJYsTlAjEghmOvlAObozSCYYnMO6nbkt6Ab3+lWqyahClzcRNcD2ouw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@snazzah/davey-linux-x64-gnu": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-linux-x64-gnu/-/davey-linux-x64-gnu-0.1.12.tgz", + "integrity": "sha512-w86fZvhJn0ErOoAQHt2UbQ95V/cgwvfvQ4GlTPQLCzt58nn+rLlXLgPn90qYlSQrZxFW38rKXwqVOMbm9p+pwQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@snazzah/davey-linux-x64-musl": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-linux-x64-musl/-/davey-linux-x64-musl-0.1.12.tgz", + "integrity": "sha512-LLNnO+hfG41ymeI+O1YHo5/0h3aKaetUNLdkBwpdJsjoyKMXZaeCnB+aHNkkupJCMPmWS0g6iPMCHUOqZSBcTg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@snazzah/davey-wasm32-wasi": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-wasm32-wasi/-/davey-wasm32-wasi-0.1.12.tgz", + "integrity": "sha512-MPKFuqYVkDFXheR7qmtEY4FWxQ/ADfgsCojQWHi13sibUqCTR9q2F1LqNn2i9IVh3sh1sxeg87fdFMCH63pl7g==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.5" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@snazzah/davey-win32-arm64-msvc": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-win32-arm64-msvc/-/davey-win32-arm64-msvc-0.1.12.tgz", + "integrity": "sha512-Uf4OYHyfbXpzyaOqIV8/h6kv166Qni5+Bxmc1E/ov4uhhKO8qXbOky8zbVOzu0U4cv5ll3s4IQ8jDAJkx/K75Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@snazzah/davey-win32-ia32-msvc": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-win32-ia32-msvc/-/davey-win32-ia32-msvc-0.1.12.tgz", + "integrity": "sha512-nRVbKTsb2ldcPI8D4BDA7P/UeiMEMvR+wYuUMp7H1pRD/3dF2hKo+MzUU+Pn78EhuYA3CWHItiAcS/GsPld67A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@snazzah/davey-win32-x64-msvc": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@snazzah/davey-win32-x64-msvc/-/davey-win32-x64-msvc-0.1.12.tgz", + "integrity": "sha512-AgUA3itPDVkxQq7RIkgE1thCiWePwWjyfOZefBBxGIlMWpRUOSwF4vY9kNLnrScyJcFULdR+Zm8PwiwV8/RKnw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@szmarczak/http-timer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", @@ -1075,6 +1378,16 @@ "node": ">=14.16" } }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/http-cache-semantics": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", diff --git a/package.json b/package.json index bcdd6f1..594d1d6 100644 --- a/package.json +++ b/package.json @@ -7,14 +7,14 @@ "type": "module", "main": "src/index.js", "engines": { - "node": ">=20" + "node": ">=22.12.0" }, "scripts": { "start": "node src/index.js", "dev": "node --watch src/index.js" }, "dependencies": { - "@discordjs/voice": "^0.18.0", + "@discordjs/voice": "^0.19.2", "@fastify/cookie": "^11.1.2", "@fastify/multipart": "^10.1.0", "@fastify/static": "^10.1.2", diff --git a/src/bot/radio.js b/src/bot/radio.js index 729c365..29cec0e 100644 --- a/src/bot/radio.js +++ b/src/bot/radio.js @@ -203,6 +203,7 @@ const NETZSCHRITT = ['Websocket auf', 'Anmeldung', 'UDP-Handschlag', 'Protokollw const ANMELDUNG = 1; const UDP_HANDSCHLAG = 2; const PROTOKOLLWAHL = 3; +const ZU = 6; // Damit dasselbe Netzteil nicht zweimal beobachtet wird. Bei einem Rückfall // baut die Bibliothek ein neues — das soll durchaus wieder mitgeschrieben @@ -257,10 +258,27 @@ export function beitrittsDiagnose(schritte) { // 19302 antwortet, TCP 2096 zum Sprachserver offen). Die Behauptung war // also falsch. Jetzt entscheidet der Mitschnitt statt einer Vermutung. const netz = schritte.netz ?? []; - const letzterSchritt = netz.filter((e) => e.schritt !== undefined).at(-1)?.schritt; const schluss = netz.filter((e) => e.schliessung !== undefined).at(-1)?.schliessung; + // Der letzte *bedeutsame* Schritt. „zu" steht immer am Ende, weil das + // Netzteil sich erst schliesst und dann den Code meldet — wer den nimmt, + // kommt nie bei einer Ursache an. Genau das ist am 14.08.2026 passiert: + // der Mitschnitt hatte die Antwort, die Auswertung hat sie verworfen. + const letzterSchritt = netz + .filter((e) => e.schritt !== undefined && e.schritt !== ZU) + .at(-1)?.schritt; const zu = schluss === undefined ? 'ohne Schliesscode' : `Schliesscode ${schluss}`; + // 4017 ist eindeutig, unabhaengig davon, wie weit es kam: Discord verlangt + // seit dem 01.03.2026 DAVE (Ende-zu-Ende-Verschluesselung) in allen + // Nicht-Stage-Sprachkanaelen und weist aeltere Gegenstellen sofort ab. + if (schluss === 4017) { + return `Discord hat die Verbindung zu **${endpunkt}** abgewiesen (4017): Sprachkanäle ` + + 'verlangen seit dem 01.03.2026 **DAVE**, die Ende-zu-Ende-Verschlüsselung. ' + + 'Dafür braucht es `@discordjs/voice` ab 0.19 samt `@snazzah/davey` — ältere ' + + 'Fassungen melden `max_dave_protocol_version: 0` und werden abgewiesen. ' + + 'Stage-Kanäle sind ausgenommen.'; + } + if (letzterSchritt === UDP_HANDSCHLAG) { // `performIPDiscovery` hat in 0.18 keine Zeitschranke und die // UDP-Keepalives werden nicht mehr ausgewertet — bleibt die Antwort @@ -345,7 +363,11 @@ export async function spielen(kanal, station) { netzteil[BEOBACHTET] = true; schritte.netz.push({ schritt: netzteil.state.code }); netzteil.on('stateChange', (_, neu) => { - if (schritte.netz.at(-1)?.schritt !== neu.code) schritte.netz.push({ schritt: neu.code }); + // Gegen den letzten *Schritt* vergleichen, nicht gegen den + // letzten Eintrag: sonst steht "zu" zweimal da, einmal vor und + // einmal nach dem Schliesscode. + const vorher = schritte.netz.filter((e) => e.schritt !== undefined).at(-1)?.schritt; + if (vorher !== neu.code) schritte.netz.push({ schritt: neu.code }); }); // Den Schliesscode wirft die Bibliothek weg: ausser bei 4014 geht // sie damit stumm zurück nach „signalling". Hier bleibt er stehen.