46 Commits
Author SHA1 Message Date
omar bdb90854f8 fix(compose): mount ./secrets read-write so yt-dlp can save cookie jar
yt-dlp calls save_cookies() on exit and rewrites the --cookies file. A read-only
mount makes it crash with "OSError: [Errno 30] Read-only file system", which surfaced
as 500s on the app's YouTube search/download endpoints when YT_COOKIE_FILE was set.
2026-06-16 07:49:30 +03:00
omarandClaude Opus 4.8 b93d476903 fix(youtube): bake JS-challenge solver into backend image + Gitea CI
Build and Publish Backend Image / build (push) Failing after 14s
YouTube playback relied on manual changes inside the running container
(deno install + /etc/yt-dlp.conf) that would be lost on any recreate.
Make it permanent and reproducible:

- Dockerfile.backend: install pinned deno 2.8.3 as yt-dlp's JS runtime and
  write a system-wide /etc/yt-dlp.conf enabling the EJS challenge solver
  (--js-runtimes deno, --remote-components ejs:github, --force-ipv4).
  Replaces the unreliable node-based config.
- .gitea/workflows/build-backend.yml: build Dockerfile.backend and push
  git.qomar.pw/omar/ts6-manager/backend:latest (amd64). Needs REGISTRY_TOKEN.
- docker-compose.yml: pull backend from the Gitea registry; frontend/sidecar
  stay on upstream clusterzx images. Mount ./secrets read-only for optional
  YouTube cookies via YT_COOKIE_FILE.
- gitignore/dockerignore: never commit cookies (live Google session).
- DEPLOY.md: deployment + CI notes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 07:27:57 +03:00
Your friendly nerd dd26e57954 Merge pull request #45 from GingerFury6/fix-video-known-limitations
fix(streaming): restore service-side presets and add separate FPS/bitrate controls
2026-03-28 19:12:59 +01:00
Philipp bbfa9d50f0 sidecar: revert GOP back to 15 frames 2026-03-23 16:05:53 +01:00
Philipp b6bd0a0eed fix(sidecar): reset RTP queues and peer stream state on source switch
Clear pending RTP packets and reset per-peer stream start state whenever
the active source is stopped or replaced.

This prevents stale queued packets and old stream gate state from leaking
into the next source, which could previously leave the sidecar stuck in a
degraded state until the container was restarted.

The change applies the same cleanup during both source stop and source
restart/switch, making repeated source changes much more robust.
2026-03-22 02:22:51 +01:00
Philipp 7b2995ca67 feat(streaming): restore preset controls and add separate FPS/bitrate tuning
Restore working output resolution presets for the sidecar service path and
extend the video streaming UI/backend with separate user-controlled FPS
and bitrate settings.

This change:
- wires resolution presets back through the sidecar service mode
- adds a dedicated framerate selection independent from resolution
- adds a dedicated video bitrate input independent from resolution
- passes resolution, FPS, and bitrate through frontend, API, backend,
  and sidecar paths
- makes local mode and service mode use the same explicit stream settings
- exposes active framerate and bitrate in stream status
- keeps preset values only as fallback defaults where appropriate

Tested successfully across multiple combinations, including:
- 480p / 720p / 1080p
- 24 FPS / 30 FPS / 60 FPS
- local files and YouTube sources
- high bitrate cases up to 1080p@60fps with 6000k video bitrate
2026-03-22 01:54:57 +01:00
Your friendly nerd d35dc5e3e2 fix(sidecar): stabilize stream sync and peer join handling (#43)
fix(sidecar): stabilize stream sync and peer join handling
2026-03-18 18:16:06 +01:00
Philipp 4868e12322 fix(sidecar): stabilize stream sync and peer join handling
fix(sidecar): stabilize stream sync and peer join handling

Rework sidecar RTP handling to improve A/V sync and make stream joins
robust under heavy repeated client requests.

This change:
- decouples UDP RTP ingestion from paced WebRTC output via queued
  audio/video processors
- adds adaptive stream pacing with configurable playout buffer and
  optional video bias for fine sync adjustment
- keeps peer output gated until a valid VP8 keyframe is available
- adds configurable queue sizes for better burst tolerance
- hardens peer creation with in-flight deduplication and safe offer reuse
- serializes answer handling per peer and ignores invalid duplicate
  answers during noisy join retries
- reduces noisy runtime logs behind a debug flag

Tested successfully with:
- YouTube sources at 30 fps and 60 fps
- local MP4 playback
- 720p and 1080p sources
- browser preview and TeamSpeak client joining in parallel
2026-03-18 02:07:44 +01:00
Clusterzx 00935dde1e Optimize Agent Flow Runner and improve Video Streaming 2026-03-12 16:41:38 +01:00
Clusterzx cca3e47f15 fix: return raw response from HTTP request bot action
Prevents axios from auto-parsing JSON responses, so plain text
responses (like BBCode widget output) are stored correctly in
temp variables via storeAs.
2026-03-11 22:39:11 +01:00
Clusterzx 238a057ce6 feat: add Player Widget button to bot card UI
- Link icon button on each bot card opens widget dialog
- Shows BBCode URL (for TS channel descriptions) and JSON URL (for websites)
- Copy-to-clipboard buttons for easy sharing
- Fetches token from /api/music-bots/:id/player-widget-token
2026-03-11 22:12:23 +01:00
Clusterzx 2cad3d058d feat: complete queue management system
Backend:
- Expose PlayQueue.index getter for current track position
- Add PlayQueue.move(from, to) for reordering
- Add POST /:id/queue/:index/play endpoint (play from queue position)
- Add PUT /:id/queue/move endpoint (reorder queue items)
- Fix currentIndex in state endpoint (was hardcoded -1)

Frontend:
- Add dedicated Queue tab with full track list
- Highlight currently playing track
- Click-to-play any track in queue
- Remove individual tracks from queue
- Move tracks up/down with buttons
- Clear queue button
- Bot selector for multi-bot setups
- Add playFromQueue and moveQueueItem API + hooks

Chat commands:
- !queue show — display queue with track numbers and durations
- !queue play <n> — jump to track at position N
- !queue remove <n> — remove track at position N
- !queue clear — clear entire queue
2026-03-11 21:59:31 +01:00
Clusterzx d3ff813129 fix: resolve issues #26, #27, #12, #29
#26 - Permissions → Client: multiple bug fixes
- Use cldbid instead of clid for client permission operations
- Add PUT/DELETE routes for clientaddperm/clientdelperm with permid resolution
- Handle error 1281 (empty result) gracefully for clients with no permissions
- Add missing case 'client' branches in frontend save mutation
- Add addClientPerm/delClientPerm to frontend API client

#27 - Music bot duplicate client on reconnect
- Add forceClose() to TS3 client for immediate socket teardown
- Add ensureDisconnected() to VoiceBot
- Add 5s grace period before reconnect attempt to let old session expire

#12 - HTTP Request node: add headers input
- Add JSON headers input field to BotEditor HTTP Request node config
- Backend already supported headers, only the UI was missing

#29 - MusicBot PlayerWidget
- Add public /api/widget/player/:botId/data endpoint (JSON)
- Add public /api/widget/player/:botId/bbcode endpoint (BBCode for channel descriptions)
- HMAC token-based auth (no DB migration needed)
- Admin endpoint to retrieve widget token and URLs
- Shows now playing, progress, and next 5 queue items
2026-03-11 14:45:51 +01:00
Clusterzx b9d65f8652 Merge branch 'dev-public' 2026-03-11 12:59:30 +01:00
Clusterzx be6757a786 fix: add GenerateCodeActionData to union type + preserve permanent channel option
- Add GenerateCodeActionData to ActionNodeData union in bot.ts
- Fix channel flag logic: only set semi_permanent when explicitly configured,
  preserving the ability to create permanent channels (TS3 default)
2026-03-11 12:59:23 +01:00
Philipp 61d1ac4783 clean-up comments
cleaned up unnecessary code comments
2026-03-11 00:21:24 +01:00
Clusterzx 01388264b5 Update README.md 2026-03-11 00:00:54 +01:00
ClusterzxandClaude Opus 4.6 c2746f6e97 feat: yt-dlp cookie management UI + Docker sidecar fixes
- Add settings routes for uploading/deleting yt-dlp cookie files (admin only)
- Add YouTube tab in Settings page with file upload, paste, and delete
- Enable --remote-components ejs:github for YouTube bot-detection bypass
- Pass cookies to resolveVideoUrl for video streaming yt-dlp calls
- Fix SidecarClient to accept full URL string (Docker networking)
- Load saved cookie file from data dir on startup
- Switch docker-compose sidecar from build to prebuilt image
- Add docker-compose.dev.yml for dev deployment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 23:55:25 +01:00
ClusterzxandClaude Opus 4.6 8cbff01d18 fix: Constrain video preview size and rebuild sidecar with A/V sync fix
Limit the WebRTC video preview player to max-w-xl (576px) to prevent
oversized preview in the WebUI. Sidecar binary rebuilt with the SSRC
resolution fix (moved to OnICEConnectionStateConnected callback).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 21:50:51 +01:00
Clusterzx 1ac052b0af test: Temp Save 2026-03-10 21:09:35 +01:00
ClusterzxandClaude Opus 4.6 b0adc7e595 fix: Remove wallclock-based A/V timestamp correction in sidecar
The previous timestamp normalization used wallclock time (time.Now())
to calculate a cross-stream offset between video (90kHz) and audio
(48kHz) RTP timestamps. This caused progressive audio/video desync
because the offset was computed once at stream start from the arrival
time of each stream's first packet — any jitter in that measurement
became a permanent drift.

FFmpeg already guarantees A/V sync within a single invocation, so no
cross-stream correction is needed. Now each stream simply subtracts
its own first timestamp to normalize to zero-based, preserving
FFmpeg's native synchronization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 20:15:03 +01:00
ClusterzxandClaude Opus 4.6 f295061aba fix: Stream stop, video quality, and UDP fragmentation
- Add reason=1 parameter to stopstream command (required by TS6 server)
- Fix stream stop order: remove viewers → stop ffmpeg → send stopstream
- Implement UDP command fragmentation for large SDP payloads (>487 bytes)
- Match yt-dlp video quality to stream preset height (avoid 360p→1080p upscale)
- Fix SidecarClient JSON parsing (handle text/plain content-type from Go)
- Resolve YouTube URLs via yt-dlp before passing to FFmpeg
- Set Content-Type header on sidecar /peer/create response
- Clean up debug logging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 19:15:50 +01:00
ClusterzxandClaude Opus 4.6 591e4ac950 feat: Video streaming via MusicBot with Go WebRTC sidecar
Extend MusicBot to stream video (YouTube, URLs, local files) to TS6
channels via WebRTC P2P. Uses a Go sidecar (Pion WebRTC + FFmpeg) for
media relay and a new stream signaling layer over the TS3 UDP protocol.

- Go sidecar: WebRTC peer management, RTP forwarding, FFmpeg control
- Stream signaling: setupstream, respondjoinstreamrequest, streamsignaling
- YouTube URL resolution via yt-dlp before passing to FFmpeg
- Quality presets (480p/720p/1080p) with configurable bitrate/framerate
- WebUI: Video tab in MusicBots page with live WebRTC preview player
- Viewer list with kick capability, chat commands (!stream, !stopstream, !viewers)
- TS3 UDP command fragmentation for large SDP payloads
- Docker: multi-stage sidecar build, separate container with SIDECAR_URL
- Graceful sidecar error handling (no backend crash on missing binary)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 17:14:58 +01:00
Philipp 9c43a64406 feat: expanding temp channel creation
expanded nodes in BotEditor:

- added password field for create and edit channel node
- added Generate Code node for automatic pw creation for custom/free/temp channels + pw can be send then via message node with temp.<name>
2026-03-10 02:23:58 +01:00
Philipp a9d0009cbe fixed temp/perm switch in channel create node
fixed temp/perm switch in channel create node
2026-03-10 01:08:42 +01:00
Philipp 0d7be581f9 QOL fixes
fixed scrollable areas for:
- yt - results
- library
- play-song dialog (song list, playlist, history)
- playlist tab

fixed analog scrollArea for radio presets.
2026-03-09 23:54:28 +01:00
Clusterzx 888f0d3088 fix: Restore radio preset scroll fix regression (#3)
Community PR merge reverted the ScrollArea→div overflow-y-auto fix.
2026-03-09 11:07:54 +01:00
Clusterzx 470858ee83 Integrate community PRs #15, #23, #25
- Voice audio improvements: stereo support + stable 20ms pacing (closes #25)
- Music request history with frontend page and API (closes #15)
- Channel-specific chat command triggers in flow automation (closes #23)
2026-03-08 21:11:21 +01:00
Clusterzx 749cfa0385 feat: Channel-specific chat command triggers in flow automation
From PR #23 by @GingerFury6:
- Command triggers can target a specific channel via channelId
- Per-channel SSH query clients move into the channel to receive textchannel events
- Unique nicknames with random suffix to avoid conflicts
- Sync/cleanup of command listeners when flows change
- Frontend: Channel ID input field + Textarea for message actions
- Backward-compatible: triggers without channelId work as before
2026-03-08 19:25:47 +01:00
Clusterzx 5a62d65b28 feat: Music request history with frontend page and API
From PR #15 by @LemDog:
- New MusicRequest Prisma model with unique constraint per server+url
- Backend routes for listing/clearing music request history
- Frontend: History tab in Play Song dialog, dedicated MusicRequests page
- Sidebar link to Music Request History
- Server logs theme fix
- Adapted to work with existing !play/!queue changes
2026-03-08 19:25:29 +01:00
Clusterzx 1d3a0ac54c feat: Voice audio improvements — stereo support + stable 20ms pacing
From PR #25 by @GingerFury6:
- Switch to stereo (2 channels) for better audio quality
- Opus encoder: CBR mode + music signal hint
- Clock-based 20ms frame pacing (prevents stutter/bursts)
- Stream buffer: chunk array instead of repeated Buffer.concat
- UDP socket: 1MB send/recv buffer size
- Debug stats behind VOICE_DEBUG=1 env var
2026-03-08 19:20:18 +01:00
Clusterzx c53a04fc2d Remove Deno, use Node.js as yt-dlp JS runtime
Deno was installed but never used in code — yt-dlp needs a JS runtime
for YouTube signature decryption and defaulted to Deno. Since Node.js 20
is already in the image, configure yt-dlp to use it via config file.

Also removes curl/unzip (only needed for Deno install), reducing image size.
Enables multi-arch (ARM64) builds by removing the arch-sensitive Deno binary.
2026-03-07 20:10:32 +01:00
Clusterzx 07a8fc3d6d Fix multiple GitHub issues (#5, #6, #7, #8, #10, #13, #16, #18)
- Fix #16: ScrollArea scroll bug — global CSS override for Radix display:table
- Fix #8: Music bot voice port no longer hardcoded to 9987, configurable per bot
- Fix #7: Long song titles no longer hide action buttons (CSS grid minmax fix)
- Fix #10: Self-signed certificate support via TS_ALLOW_SELF_SIGNED env var
- Fix #5: YouTube cookie file support via YT_COOKIE_FILE env var for yt-dlp
- Fix #18: Widget improvements — spacer channel rendering (SVG + HTML),
  hide empty channels option, click-to-join ts3server:// links
- Fix #13: SSH reconnect hardened — TCP keepalive via ssh2, application-level
  keepalive with failure detection, forceDisconnect, double-reconnect guard
- Fix #6: Add !queue/!add chat commands to enqueue songs without interrupting
  current playback; !play now queues when already playing
2026-03-07 19:31:11 +01:00
Clusterzx 33623336d5 Merge branch 'main' of https://github.com/clusterzx/ts6-manager 2026-02-25 20:48:40 +01:00
Clusterzx 3a91bf744b Fix for issue #2 #3 #4 2026-02-25 20:48:38 +01:00
Your friendly nerd dd80a4fe91 Add disclaimer and AI Assisted badge to README
Added a disclaimer section and an AI Assisted badge to the README.
2026-02-25 20:13:19 +01:00
Clusterzx 87edf3efd9 Remove unneccesary debug messages 2026-02-25 16:22:40 +01:00
Clusterzx 931fd8abf6 Update Readme 2026-02-25 16:08:45 +01:00
Clusterzx 98752fb33b Security hardening: setup wizard, credential encryption, SSRF protection, token rotation, RBAC enforcement, and README overhaul
- Replace hardcoded admin/admin with setup wizard (/setup) for initial account creation
  - Add AES-256-GCM encryption for stored API keys, SSH passwords, and bot identity data
  - Add SSRF protection (private IP blocking, DNS rebinding prevention) on all outbound URLs
  - Add refresh token reuse detection with automatic family revocation
  - Add rate limiting on auth endpoints (15 req/15min)
  - Add per-server access control middleware (UserServerAccess enforcement)
  - Add WebQuery command whitelist blocking destructive commands in bot flows
  - Add JWT startup guard (refuse to start in production with default secret)
  - Add WebSocket authentication via JWT query parameter
  - Add mandatory webhook secrets with timing-safe comparison
  - Add password complexity requirements (8+ chars, mixed case, digit)
  - Add ENCRYPTION_KEY env var to docker-compose files
  - Restrict JWT verification to HS256 algorithm
  - Restrict client IP visibility to admin role
  - Add parameter whitelists for instanceedit and serveredit
  - Bound widget cache size with periodic cleanup
  - Redact server version/platform in widget API
  - Rewrite README with updated features, setup instructions, and env vars
2026-02-25 16:06:00 +01:00
Clusterzx 0aa6ce68db Embeddable server status widgets with 6 themes (Dark, Light, transparent, Neon/Cyberpunk, Military, Minimal).
Supports iframe, SVG and PNG output
  for forums, signatures and external websites.

  - Public endpoints: /widget/:token (iframe), /api/widget/:token/image.svg,
    /api/widget/:token/image.png — no auth required, 45s cache, CORS *
  - Admin CRUD via /api/widgets with token generation/rotation
  - Widget management modal on Dashboard page with embed code tabs
    (iframe snippet, image URLs, BBCode) and live preview
  - Prisma Widget model, shared theme definitions in @ts6/common
  - Server-side SVG generation with @resvg/resvg-js PNG rendering
  - Nginx config: X-Frame-Options override for /widget/ path
2026-02-25 11:40:10 +01:00
Clusterzx 15fd90e927 Fixed endless reconnection bug when a previously created bot had no server password, but the server has. Now fully error aware to the rejection reason. 2026-02-25 09:44:26 +01:00
Clusterzx 9770cff1be Added Password field to MusicBot 2026-02-25 09:31:42 +01:00
Clusterzx 82ec163df4 Update Reamde "Quick Start" Part 2026-02-24 22:52:20 +01:00
Clusterzx 31c87351f8 Missed the files for previous commit ... lol 2026-02-24 22:51:01 +01:00
Clusterzx d48b986065 Update Readme.md with images + recreated docker-compose with hub and local version 2026-02-24 22:50:31 +01:00
Clusterzx a8ad91fd18 Initial commit 2026-02-24 22:33:33 +01:00