mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-02 04:52:50 +08:00
feat(setup)!: require Node 22.12+ and drop Node 20 (#152)
better-sqlite3 stopped publishing prebuilt binaries for Node 20's ABI
(115) in 12.10.0 - upstream, not a mirror gap:
12.8.0 / 12.9.0 115 127 131 137 141
12.10.0+ 127 137 141 147
`better-sqlite3: ^12.8.0` resolves well past that, so every Node 20
install 404'd on the CDN, fell through to the source build, and demanded
Python plus a C++ toolchain before the bot could start at all. package.json
went on claiming `^20.19.0` worked, and the README went on recommending
Node 20 as one of two blessed versions. It was not a supported
configuration in any meaningful sense - it was a trap.
So say so up front: engines, both setup scripts, and the Docker images now
require Node 22.12+ (or 24+, which still needs a source build for opus).
The version gate in setup.bat / setup.sh is kept byte-identical to the
engines range, as before.
Also copy scripts/lib/console-log.mjs into the production image. The
previous commit had check-native.mjs import it, and the Dockerfile copies
check-native.mjs in on its own for `docker exec ... npm start` - without
its dependency that preflight now dies with ERR_MODULE_NOT_FOUND.
BREAKING CHANGE: Node 20 is no longer supported. Node 22.12 LTS or newer
is required; setup refuses to run on anything older.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
5e9ae49f52
commit
a804b2edc1
6 files changed
+35
-29
No files matched your search
@@ -76,11 +76,11 @@
|
|||||||
>
|
>
|
||||||
> 之后 `setup.bat` 会运行 `npm install` 安装所有依赖(包括内置 FFmpeg),按当前 Node 版本准备好原生模块,最后构建项目。之后每次只需双击 `start.bat` 启动。
|
> 之后 `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 **已自动内置**,无需手动安装。
|
FFmpeg **已自动内置**,无需手动安装。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
"description": "TeamSpeak music bot with NetEase Cloud Music and QQ Music support",
|
"description": "TeamSpeak music bot with NetEase Cloud Music and QQ Music support",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
"node": "^22.12.0 || >=24.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "tsx watch src/index.ts",
|
"dev": "tsx watch src/index.ts",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
# ==========================================
|
# ==========================================
|
||||||
|
|
||||||
# --- Stage 1: Build backend + frontend ---
|
# --- 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)
|
# Install build tools for native modules (opus, better-sqlite3)
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
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
|
RUN rm -rf node_modules && npm ci --production && npm cache clean --force
|
||||||
|
|
||||||
# --- Stage 2: Production image ---
|
# --- Stage 2: Production image ---
|
||||||
FROM node:20-slim
|
FROM node:22-slim
|
||||||
|
|
||||||
# Install system FFmpeg — the ffmpeg-static npm package bundles a pre-compiled
|
# Install system FFmpeg — the ffmpeg-static npm package bundles a pre-compiled
|
||||||
# binary that can SIGSEGV inside Docker (incompatible glibc / missing libs).
|
# 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
|
# goes through npm, but an interactive `docker exec ... npm start` would
|
||||||
# otherwise die on a missing script rather than starting the bot.
|
# otherwise die on a missing script rather than starting the bot.
|
||||||
COPY --from=builder /app/scripts/check-native.mjs ./scripts/check-native.mjs
|
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
|
# Data directory for database, cookies, logs
|
||||||
RUN mkdir -p /app/data
|
RUN mkdir -p /app/data
|
||||||
|
|||||||
@@ -417,11 +417,12 @@ function buildFromSource(command) {
|
|||||||
/**
|
/**
|
||||||
* A 404 from the CDN is not a mirror outage: it means this exact package
|
* 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.
|
* 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 no build for Node 24 (ABI 137), so a user on that
|
||||||
* @discordjs/opus 0.10.0 has none for Node 24 (ABI 137) - so a user on either
|
* major lands in the source-build fallback below and is told to install Python
|
||||||
* of those majors lands in the source-build fallback below and is told to
|
* and a C++ toolchain. Switching Node major is the far cheaper fix, and nothing
|
||||||
* install Python and a C++ toolchain. Switching Node major is the far cheaper
|
* else in this output points at it. (better-sqlite3 dropping its Node 20 / ABI
|
||||||
* fix, and nothing else in this output points at it. See issue #152.
|
* 115 builds in 12.10.0 is why Node 20 is no longer accepted at all.)
|
||||||
|
* See issue #152.
|
||||||
*/
|
*/
|
||||||
function explainMissingPrebuild(name, version, err) {
|
function explainMissingPrebuild(name, version, err) {
|
||||||
if (!/HTTP 404/.test(err.message)) return;
|
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
|
// 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
|
// 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
|
// 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
|
// race: @discordjs/opus 0.10.0 has no prebuild for ABI 137, so on Node 24 that
|
||||||
// better-sqlite3 prebuild for ABI 115 (Node 20), so on both of the Node
|
// module 404s within ~100ms and starts building while ffmpeg's ~80MB download
|
||||||
// versions this project supports, one module 404s within ~100ms and starts
|
// is still going. ffmpeg is optional,
|
||||||
// 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
|
// 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.
|
// reported success — leaving the user with no ffmpeg and no working playback.
|
||||||
// Nothing here benefits from overlap anyway: every probe is execFileSync.
|
// Nothing here benefits from overlap anyway: every probe is execFileSync.
|
||||||
|
|||||||
+11
-9
@@ -11,7 +11,7 @@ title TSMusicBot Setup
|
|||||||
:: ============================================================
|
:: ============================================================
|
||||||
|
|
||||||
set "SCRIPT_VERSION=2.2"
|
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
|
:: 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.
|
:: still works, it just may have no prebuilt addons and fall back to a source build.
|
||||||
set "TESTED_NODE_MAJOR=22"
|
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%"
|
call :log "Node.js version: %NODE_VER%"
|
||||||
echo [OK] Node.js found: %NODE_VER%
|
echo [OK] Node.js found: %NODE_VER%
|
||||||
|
|
||||||
:: The supported floor is not just a major version, so let node decide:
|
:: The supported floor is not just a major version, so let node decide.
|
||||||
:: @honeybbq/teamspeak-client needs >=20.19, @sansenjian/qq-music-api needs
|
:: Node 20 was dropped: better-sqlite3 ships no prebuilt binary for its ABI
|
||||||
:: >=20.17 / >=22.9, and the odd majors (21 / 23) are excluded by
|
:: (115) since 12.10.0, so every Node 20 install needed Python and a C++
|
||||||
:: better-sqlite3 and vitest. Keep this in sync with "engines" in package.json.
|
:: toolchain just to get off the ground (issue #152). The odd majors (21 /
|
||||||
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)"
|
:: 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 (
|
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/
|
echo Download: https://nodejs.org/ or https://nodejs.cn/
|
||||||
pause
|
pause
|
||||||
exit /b 1
|
exit /b 1
|
||||||
@@ -86,10 +88,10 @@ if errorlevel 1 (
|
|||||||
:: characters and starts eating the "echo " prefix of following lines.
|
:: characters and starts eating the "echo " prefix of following lines.
|
||||||
:: Bilingual guidance lives in the Node scripts, which print UTF-8 reliably.
|
:: Bilingual guidance lives in the Node scripts, which print UTF-8 reliably.
|
||||||
if %NODE_MAJOR% GTR %TESTED_NODE_MAJOR% (
|
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 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 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%.
|
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%"
|
call :log "[WARN] Node major %NODE_MAJOR% is newer than tested LTS %TESTED_NODE_MAJOR%"
|
||||||
)
|
)
|
||||||
|
|||||||
+8
-6
@@ -32,16 +32,18 @@ echo "[OK] Node.js $(node -v)"
|
|||||||
TESTED_NODE_MAJOR=22
|
TESTED_NODE_MAJOR=22
|
||||||
NODE_MAJOR="$(node -p 'process.versions.node.split(".")[0]')"
|
NODE_MAJOR="$(node -p 'process.versions.node.split(".")[0]')"
|
||||||
|
|
||||||
# The floor is not just a major version, so let node decide: @honeybbq/teamspeak-client
|
# The floor is not just a major version, so let node decide. Node 20 was dropped:
|
||||||
# needs >=20.19, @sansenjian/qq-music-api needs >=20.17 / >=22.9, and the odd majors
|
# better-sqlite3 ships no prebuilt binary for its ABI (115) since 12.10.0, so every
|
||||||
# (21 / 23) are excluded by better-sqlite3 and vitest. Keep in sync with package.json "engines".
|
# Node 20 install needed Python and a C++ toolchain just to get off the ground
|
||||||
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
|
# (issue #152). The odd majors (21 / 23) are excluded by better-sqlite3 and vitest.
|
||||||
echo "[ERROR] Node.js $(node -v) is not supported. Use Node 20.19+ LTS or Node 22.12+ LTS."
|
# 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/"
|
echo " https://nodejs.org/ | https://nodejs.cn/"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if [ "$NODE_MAJOR" -gt "$TESTED_NODE_MAJOR" ]; then
|
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 " 新版 Node 可能没有现成的 opus / better-sqlite3 预编译包,"
|
||||||
echo " 安装时会自动改用源码编译,需要 C/C++ 构建工具,速度较慢。"
|
echo " 安装时会自动改用源码编译,需要 C/C++ 构建工具,速度较慢。"
|
||||||
echo " This is only a warning - setup builds the binaries for $(node -v) either way."
|
echo " This is only a warning - setup builds the binaries for $(node -v) either way."
|
||||||
|
|||||||
Reference in new issue
Block a user