diff --git a/README.md b/README.md index dc66a32..e58cd4b 100644 --- a/README.md +++ b/README.md @@ -76,11 +76,11 @@ > > 之后 `setup.bat` 会运行 `npm install` 安装所有依赖(包括内置 FFmpeg),按当前 Node 版本准备好原生模块,最后构建项目。之后每次只需双击 `start.bat` 启动。 > -> 其他 Node 大版本也能用,但通常没有现成的预编译包,安装脚本会改用源码编译,需要 Python + C/C++ 构建工具且耗时更久:better-sqlite3 从 12.10.0 起不再提供 Node 20(ABI 115)的预编译包,@discordjs/opus 0.10.0 也没有 Node 24(ABI 137)的——所以推荐 22 LTS。**装好之后不要再换 Node 大版本**:原生模块只能在编译它的那个版本上加载,换版本后必须重新运行 `setup.bat`(脚本会自动检测并重装,见下方常见问题)。 +> **Node 20 已不再支持**:better-sqlite3 从 12.10.0 起不再发布它那个 ABI(115)的预编译包,装起来必须先备好 Python + C++ 构建工具([#152](https://github.com/ZHANGTIANYAO1/teamspeak-music-bot/issues/152))。Node 24 及更新的大版本能用,但 @discordjs/opus 0.10.0 同样没有 Node 24(ABI 137)的预编译包,安装脚本会改用源码编译,需要构建工具且耗时更久——所以推荐 22 LTS。**装好之后不要再换 Node 大版本**:原生模块只能在编译它的那个版本上加载,换版本后必须重新运行 `setup.bat`(脚本会自动检测并重装,见下方常见问题)。 ### 方式二:手动安装(所有系统) -**前置条件:** [Node.js 22 LTS](https://nodejs.org/)(推荐;Node 20 / 24 等其他大版本可用,但需要源码编译原生模块)和一个 TeamSpeak 服务器(TS3/TS5/TS6 均可)。 +**前置条件:** [Node.js 22 LTS](https://nodejs.org/)(Node 24 及更新版本也能用,但需要源码编译原生模块;Node 20 已不再支持)和一个 TeamSpeak 服务器(TS3/TS5/TS6 均可)。 FFmpeg **已自动内置**,无需手动安装。 ```bash diff --git a/package.json b/package.json index 1cdd85a..0c52047 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "TeamSpeak music bot with NetEase Cloud Music and QQ Music support", "type": "module", "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.12.0 || >=24.0.0" }, "scripts": { "dev": "tsx watch src/index.ts", diff --git a/scripts/docker/Dockerfile b/scripts/docker/Dockerfile index 735bb33..84fe8d9 100644 --- a/scripts/docker/Dockerfile +++ b/scripts/docker/Dockerfile @@ -4,7 +4,7 @@ # ========================================== # --- Stage 1: Build backend + frontend --- -FROM node:20-slim AS builder +FROM node:22-slim AS builder # Install build tools for native modules (opus, better-sqlite3) RUN apt-get update && apt-get install -y --no-install-recommends \ @@ -30,7 +30,7 @@ RUN npm run build RUN rm -rf node_modules && npm ci --production && npm cache clean --force # --- Stage 2: Production image --- -FROM node:20-slim +FROM node:22-slim # Install system FFmpeg — the ffmpeg-static npm package bundles a pre-compiled # binary that can SIGSEGV inside Docker (incompatible glibc / missing libs). @@ -51,6 +51,8 @@ COPY --from=builder /app/node_modules ./node_modules # goes through npm, but an interactive `docker exec ... npm start` would # otherwise die on a missing script rather than starting the bot. COPY --from=builder /app/scripts/check-native.mjs ./scripts/check-native.mjs +# ...and the module it imports for crash-proof logging. +COPY --from=builder /app/scripts/lib/console-log.mjs ./scripts/lib/console-log.mjs # Data directory for database, cookies, logs RUN mkdir -p /app/data diff --git a/scripts/download-binaries.mjs b/scripts/download-binaries.mjs index df6b68d..616b3be 100755 --- a/scripts/download-binaries.mjs +++ b/scripts/download-binaries.mjs @@ -417,11 +417,12 @@ function buildFromSource(command) { /** * A 404 from the CDN is not a mirror outage: it means this exact package * version publishes no prebuilt binary for the running Node ABI at all. - * better-sqlite3 dropped its Node 20 (ABI 115) builds in 12.10.0, and - * @discordjs/opus 0.10.0 has none for Node 24 (ABI 137) - so a user on either - * of those majors lands in the source-build fallback below and is told to - * install Python and a C++ toolchain. Switching Node major is the far cheaper - * fix, and nothing else in this output points at it. See issue #152. + * @discordjs/opus 0.10.0 has no build for Node 24 (ABI 137), so a user on that + * major lands in the source-build fallback below and is told to install Python + * and a C++ toolchain. Switching Node major is the far cheaper fix, and nothing + * else in this output points at it. (better-sqlite3 dropping its Node 20 / ABI + * 115 builds in 12.10.0 is why Node 20 is no longer accepted at all.) + * See issue #152. */ function explainMissingPrebuild(name, version, err) { if (!/HTTP 404/.test(err.message)) return; @@ -694,10 +695,9 @@ try { // that same loop. Run these concurrently and the first module to fall back to // a source build kills every download still in flight — the connection is // healthy, the timer just never got a chance to be reset. That is not a rare - // race: npmmirror has no opus prebuild for ABI 137 (Node 24) and no - // better-sqlite3 prebuild for ABI 115 (Node 20), so on both of the Node - // versions this project supports, one module 404s within ~100ms and starts - // building while ffmpeg's ~80MB download is still going. ffmpeg is optional, + // race: @discordjs/opus 0.10.0 has no prebuild for ABI 137, so on Node 24 that + // module 404s within ~100ms and starts building while ffmpeg's ~80MB download + // is still going. ffmpeg is optional, // so the spurious failure used to be swallowed as a WARN and setup still // reported success — leaving the user with no ffmpeg and no working playback. // Nothing here benefits from overlap anyway: every probe is execFileSync. diff --git a/scripts/setup.bat b/scripts/setup.bat index e1fb536..f05b3f9 100644 --- a/scripts/setup.bat +++ b/scripts/setup.bat @@ -11,7 +11,7 @@ title TSMusicBot Setup :: ============================================================ set "SCRIPT_VERSION=2.2" -set "MIN_NODE_MAJOR=20" +set "MIN_NODE_MAJOR=22" :: Newest Node major this project is regularly tested against. Anything above :: still works, it just may have no prebuilt addons and fall back to a source build. set "TESTED_NODE_MAJOR=22" @@ -67,13 +67,15 @@ for /f "tokens=1 delims=v." %%a in ("%NODE_VER%") do set "NODE_MAJOR=%%a" call :log "Node.js version: %NODE_VER%" echo [OK] Node.js found: %NODE_VER% -:: The supported floor is not just a major version, so let node decide: -:: @honeybbq/teamspeak-client needs >=20.19, @sansenjian/qq-music-api needs -:: >=20.17 / >=22.9, and the odd majors (21 / 23) are excluded by -:: better-sqlite3 and vitest. Keep this in sync with "engines" in package.json. -node -e "const v=process.versions.node.split('.').map(Number); process.exit((v[0]===20&&v[1]>=19)||(v[0]===22&&v[1]>=12)||v[0]>=24?0:1)" +:: The supported floor is not just a major version, so let node decide. +:: Node 20 was dropped: better-sqlite3 ships no prebuilt binary for its ABI +:: (115) since 12.10.0, so every Node 20 install needed Python and a C++ +:: toolchain just to get off the ground (issue #152). The odd majors (21 / +:: 23) are excluded by better-sqlite3 and vitest. +:: Keep this in sync with "engines" in package.json. +node -e "const v=process.versions.node.split('.').map(Number); process.exit((v[0]===22&&v[1]>=12)||v[0]>=24?0:1)" if errorlevel 1 ( - call :error "Node.js %NODE_VER% is not supported. Use Node 20.19+ LTS or Node 22.12+ LTS." + call :error "Node.js %NODE_VER% is not supported. Use Node 22.12+ LTS or newer." echo Download: https://nodejs.org/ or https://nodejs.cn/ pause exit /b 1 @@ -86,10 +88,10 @@ if errorlevel 1 ( :: characters and starts eating the "echo " prefix of following lines. :: Bilingual guidance lives in the Node scripts, which print UTF-8 reliably. if %NODE_MAJOR% GTR %TESTED_NODE_MAJOR% ( - echo [WARN] Node %NODE_VER% is newer than the tested LTS line, Node 20 / Node 22. + echo [WARN] Node %NODE_VER% is newer than the tested LTS line, Node 22. echo Newer Node majors may have no prebuilt opus / better-sqlite3, echo so setup falls back to a source build - slower, needs C++ build tools. - echo Recommended: Node 20 LTS or Node 22 LTS - https://nodejs.org/ or https://nodejs.cn/ + echo Recommended: Node 22 LTS - https://nodejs.org/ or https://nodejs.cn/ echo This is only a warning; setup still builds the binaries for %NODE_VER%. call :log "[WARN] Node major %NODE_MAJOR% is newer than tested LTS %TESTED_NODE_MAJOR%" ) diff --git a/scripts/setup.sh b/scripts/setup.sh index d54bf44..154b2f4 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -32,16 +32,18 @@ echo "[OK] Node.js $(node -v)" TESTED_NODE_MAJOR=22 NODE_MAJOR="$(node -p 'process.versions.node.split(".")[0]')" -# The floor is not just a major version, so let node decide: @honeybbq/teamspeak-client -# needs >=20.19, @sansenjian/qq-music-api needs >=20.17 / >=22.9, and the odd majors -# (21 / 23) are excluded by better-sqlite3 and vitest. Keep in sync with package.json "engines". -if ! node -e 'const v=process.versions.node.split(".").map(Number); process.exit((v[0]===20&&v[1]>=19)||(v[0]===22&&v[1]>=12)||v[0]>=24?0:1)'; then - echo "[ERROR] Node.js $(node -v) is not supported. Use Node 20.19+ LTS or Node 22.12+ LTS." +# The floor is not just a major version, so let node decide. Node 20 was dropped: +# better-sqlite3 ships no prebuilt binary for its ABI (115) since 12.10.0, so every +# Node 20 install needed Python and a C++ toolchain just to get off the ground +# (issue #152). The odd majors (21 / 23) are excluded by better-sqlite3 and vitest. +# Keep in sync with package.json "engines". +if ! node -e 'const v=process.versions.node.split(".").map(Number); process.exit((v[0]===22&&v[1]>=12)||v[0]>=24?0:1)'; then + echo "[ERROR] Node.js $(node -v) is not supported. Use Node 22.12+ LTS or newer." echo " https://nodejs.org/ | https://nodejs.cn/" exit 1 fi if [ "$NODE_MAJOR" -gt "$TESTED_NODE_MAJOR" ]; then - echo "[WARN] Node $(node -v) is newer than the tested LTS line (Node 20 / Node 22)." + echo "[WARN] Node $(node -v) is newer than the tested LTS line (Node 22)." echo " 新版 Node 可能没有现成的 opus / better-sqlite3 预编译包," echo " 安装时会自动改用源码编译,需要 C/C++ 构建工具,速度较慢。" echo " This is only a warning - setup builds the binaries for $(node -v) either way."