Commit Graph
16 Commits
Author SHA1 Message Date
Claude b00b6637d2 Fix corner cases in connect/disconnect lifecycle and resource cleanup
1. Move TS6 handler patch to after client.connect() — the library's
   connect() internally replaces handler via #S(), discarding any
   patch applied beforehand. Patching after connect() is safe because
   clientinit is sent in async message callbacks after Init1 round-trips.

2. Preserve detectedProtocol across reconnect — disconnect() resets it
   to "unknown", causing the TS6 patch to be skipped on reconnect.

3. Prevent double "disconnected" event in BotInstance — disconnect()
   emitted it directly AND the async TS3Client disconnect triggered
   another through the event chain.

4. Guard playNext() against running after disconnect — check connected
   flag to avoid ghost queue processing.

5. Fix UDP error timer leak — clear previous timer before setting a new
   one to prevent accumulation.

6. Fix isPortFree() FD leak — close the test server on error path.

https://claude.ai/code/session_01QzvMLUT3UkhsffShcY1qzD
2026-04-04 15:26:41 +00:00
Claude 7ad9559653 Fix TS6 connection: patch clientinit version at handler level
The @honeybbq/teamspeak-client library sends clientinit directly via
handler.sendPacket() during the handshake, bypassing the commandMiddleware
chain entirely. This meant the ts6VersionMiddleware never intercepted the
handshake clientinit, so TS6 servers always received version 3.5.3 and
silently rejected it (never responding with initserver), causing idle timeout.

Fix: monkey-patch handler.sendPacket() to intercept clientinit packets and
upgrade the version to 3.6.2 before they're sent over the wire.

https://claude.ai/code/session_01QzvMLUT3UkhsffShcY1qzD
2026-04-04 14:24:06 +00:00
Claude 80e92b77b8 Fix install.sh: build from source instead of requiring pre-built dist
The script previously checked for a dist/ directory and failed with
"Please run this script from the TSMusicBot source directory after
building" — requiring users to manually build before installing.

Now the script:
- Resolves project root from script location (works from any cwd)
- Installs build tools (build-essential/gcc) for native modules
- Runs npm install + npm run build automatically
- Copies built artifacts to /opt/tsmusicbot
- Creates data directory for runtime files
- Adds journalctl command to the help output

https://claude.ai/code/session_016WhH58avUD9xy2dgADJgTh
2026-04-03 14:25:08 +00:00
Claude 185f592ce9 Update README for dev branch with TS3/TS6 dual protocol changelog
- Add dev branch notice and changelog section at the top
- Add TS3/TS6 badges
- Document new protocol modules (protocol-detect, http-query, ts6-compat)
- List all bug fixes in dev branch
- Update architecture diagram with new ts-protocol files
- Add TS6 Server FAQ entry
- Credit NeteaseTSBot for TS6 protocol reference

https://claude.ai/code/session_016WhH58avUD9xy2dgADJgTh
2026-04-03 14:01:01 +00:00
Claude 1379a062ba Add TS6 clientinit version middleware and fix playNext retry bug
clientinit compatibility:
- Analyzed @honeybbq/teamspeak-client's clientinit: it already sends a
  clean 14-field payload without problematic fields (no badges,
  integrations, security_hash, etc.)
- The key difference vs NeteaseTSBot is client_version: our library
  sends 3.5.3, NeteaseTSBot sends 3.6.2. TS6 servers may reject
  older versions.
- Add ts6-compat.ts with CommandMiddleware that patches clientinit
  to use version 3.6.2 + matching ECDSA signature when connecting
  to detected TS6 servers
- Middleware is automatically applied when detectedProtocol === "ts6"

Pre-existing bug fix:
- Fix playNext() in instance.ts where successful retry still fell
  through to player.stop(), killing the just-started playback

https://claude.ai/code/session_016WhH58avUD9xy2dgADJgTh
2026-04-03 13:46:31 +00:00
Claude 6184f38330 Fix 7 corner cases found in second review pass
Critical:
- Persist serverProtocol/ts6ApiKey in database schema so TS6 config
  survives restarts (added columns + manager save/load)

Medium:
- Clear udpErrorTimer on disconnect to prevent memory leak and stale
  log messages from firing after teardown
- Guard against double connect() by disconnecting old client first
- Add settled guard in TS6HttpQuery.request() to prevent double
  reject when both res error and req error fire
- Add res.on("error") handler to TS6HttpQuery response stream

Low:
- Cap probeTS3Query banner buffer at 256 bytes to prevent memory abuse
  from non-TS3 services sending large data on port 10011
- Remove unnecessary EventEmitter inheritance from TS6HttpQuery
- Update database test fixtures with new serverProtocol/ts6ApiKey fields

https://claude.ai/code/session_016WhH58avUD9xy2dgADJgTh
2026-04-03 13:38:49 +00:00
Claude 9e45193e2c Fix corner cases in protocol detection and connection cleanup
- Fix double-resolve race in probeTS3Query (data event vs connect timer)
  by guarding with a resolved flag
- Fix double-resolve in probeTS6HttpQuery similarly
- Support custom query ports in detectServerProtocol via DetectOptions
- Clean up httpQuery and detectedProtocol on disconnect()
- Add res.on("error") handler in HTTP Query client to avoid unhandled errors
- Improve logging: warn with actionable message when protocol is unknown

https://claude.ai/code/session_016WhH58avUD9xy2dgADJgTh
2026-04-03 13:34:37 +00:00
Claude e5fd35da32 Update package-lock.json after dependency install
https://claude.ai/code/session_016WhH58avUD9xy2dgADJgTh
2026-04-03 13:04:17 +00:00
Claude 9e51ba6cd4 Add dual TS3/TS6 protocol support with auto-detection
The @honeybbq/teamspeak-client library already handles TS6 license block
type 8 (Ts5Server) in its handshake, so voice connections work with both
TS3 and TS6 servers. This commit adds the surrounding infrastructure:

- protocol-detect.ts: Auto-detect server type by probing TS3 ServerQuery
  (port 10011) and TS6 HTTP Query (port 10080) in parallel
- http-query.ts: TS6 HTTP Query client replacing the raw-TCP ServerQuery
  that TS6 servers no longer support (ports 10080/10443)
- client.ts: Protocol-aware connection with auto-detection, TS6 HTTP
  Query setup, and forced protocol override option
- manager.ts: Pass through serverProtocol and ts6ApiKey config options
- connection.ts: Mark legacy TS3 ServerQuery as deprecated for TS6

https://claude.ai/code/session_016WhH58avUD9xy2dgADJgTh
2026-04-03 13:03:47 +00:00
Claude 1c88dd7a35 Add comprehensive error handling to prevent process crashes
- Global uncaughtException/unhandledRejection handlers in index.ts
- FFmpeg stdout/stderr stream error handlers in player.ts
- HTTP server and WebSocket server error handlers in server.ts
- Safe WebSocket broadcast with try-catch in websocket.ts
- Catch async errors from textMessage handler in instance.ts
- Reset voiceFramesSent counter on reconnect in client.ts

https://claude.ai/code/session_01EjpEsC2GCsvwbu4n3XC8EE
2026-03-31 16:58:14 +00:00
Claude 168f9f0286 Fix EINTR crash from pino ThreadStream during FFmpeg playback
The pino logger's ThreadStream was throwing unhandled EINTR errors
when FFmpeg child processes were spawned, crashing the entire bot.
Add an error handler to suppress EINTR and prevent process crashes.

https://claude.ai/code/session_01EjpEsC2GCsvwbu4n3XC8EE
2026-03-31 16:52:53 +00:00
Claude 1993f84fad Fix FFmpeg binary resolution: test binary actually works before using it
The ffmpeg-static bundled binary was crashing immediately (exitCode: null,
no data produced). Now we run `ffmpeg -version` to verify the binary works
before selecting it, with automatic fallback to system ffmpeg.

Also logs ffmpeg binary path at info level and captures signal in close event.

https://claude.ai/code/session_01EjpEsC2GCsvwbu4n3XC8EE
2026-03-31 16:40:38 +00:00
Claude 1a880ef20b Add diagnostic logging for playback pipeline debugging
Adds info-level logs at each stage of the audio pipeline to help
diagnose why playback produces no audible output:
- FFmpeg first PCM data received
- FFmpeg process exit code
- FFmpeg stderr (errors/HTTP/stream info at info level)
- First opus frame encoded and emitted
- First voice packet sent to TeamSpeak
- Error catching in frame encoding loop

https://claude.ai/code/session_01EjpEsC2GCsvwbu4n3XC8EE
2026-03-31 16:30:53 +00:00
Claude 89407d9694 docs: add FFmpeg EACCES troubleshooting to README
https://claude.ai/code/session_01CqfKgV8GuCmWNpfx86H62X
2026-03-31 16:04:39 +00:00
Claude 9e52b0bda9 refactor: cache resolved ffmpeg path at module load time
Avoid repeated filesystem checks on every play() call by resolving
the ffmpeg binary path once at module load. Also verify execute
permission after chmod to handle noexec mounts.

https://claude.ai/code/session_01CqfKgV8GuCmWNpfx86H62X
2026-03-31 16:02:00 +00:00
Claude 58caff3209 fix: auto-fix ffmpeg binary execute permission on startup
The bundled ffmpeg-static binary may lose execute permission after npm
install on some platforms, causing EACCES errors during playback. Now
checks and fixes the permission automatically before spawning ffmpeg.

https://claude.ai/code/session_01CqfKgV8GuCmWNpfx86H62X
2026-03-31 15:58:54 +00:00