{"id":46662473,"url":"https://github.com/yichen11818/neteasetsbot","last_synced_at":"2026-04-13T01:31:47.367Z","repository":{"id":332801698,"uuid":"1134352097","full_name":"yichen11818/NeteaseTSBot","owner":"yichen11818","description":"TSBot 是一个为 TeamSpeak 制作的网易云音乐机器人，提供网易云音乐播放及网页服务,一键式启动与安装,免除繁杂的依赖安装","archived":false,"fork":false,"pushed_at":"2026-03-08T11:16:48.000Z","size":2386,"stargazers_count":27,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-08T14:49:46.649Z","etag":null,"topics":["neteasecloudmusicapi","teamspeak","teamspeak3-bot","teamspeak6"],"latest_commit_sha":null,"homepage":"","language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yichen11818.png","metadata":{"files":{"readme":"README.en.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-14T15:49:16.000Z","updated_at":"2026-03-08T12:13:40.000Z","dependencies_parsed_at":"2026-01-15T19:02:02.142Z","dependency_job_id":null,"html_url":"https://github.com/yichen11818/NeteaseTSBot","commit_stats":null,"previous_names":["yichen11818/neteasetsbot"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/yichen11818/NeteaseTSBot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yichen11818%2FNeteaseTSBot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yichen11818%2FNeteaseTSBot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yichen11818%2FNeteaseTSBot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yichen11818%2FNeteaseTSBot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yichen11818","download_url":"https://codeload.github.com/yichen11818/NeteaseTSBot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yichen11818%2FNeteaseTSBot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30618049,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-17T04:46:40.957Z","status":"ssl_error","status_checked_at":"2026-03-17T04:46:32.538Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["neteasecloudmusicapi","teamspeak","teamspeak3-bot","teamspeak6"],"created_at":"2026-03-08T13:04:32.843Z","updated_at":"2026-04-13T01:31:47.350Z","avatar_url":"https://github.com/yichen11818.png","language":"Vue","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TSBot (NeteaseTSBot)\n\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n![Platform](https://img.shields.io/badge/platform-Linux-informational)\n![Python](https://img.shields.io/badge/python-3.8%2B-blue)\n![Node](https://img.shields.io/badge/node-16%2B-brightgreen)\n![Rust](https://img.shields.io/badge/rust-1.70%2B-orange)\n![FastAPI](https://img.shields.io/badge/FastAPI-0.115.6-009688?logo=fastapi\u0026logoColor=white)\n![Vue](https://img.shields.io/badge/Vue-3-42b883?logo=vue.js\u0026logoColor=white)\n![Vite](https://img.shields.io/badge/Vite-5-646CFF?logo=vite\u0026logoColor=white)\n![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)\n[![中文 README](https://img.shields.io/badge/README-%E4%B8%AD%E6%96%87-red)](README.md)\n\nTSBot is a TeamSpeak based music bot; the `voice-service` primary client connection already supports TS6 (historical env var names remain `TSBOT_TS3_*`). It provides:\n\n- **TeamSpeak voice playback** (connects to TeamSpeak servers and plays audio via `voice-service`; primary client connection supports TS3/TS6)\n- **Queue and playback control** (pause/resume/next/previous, volume, shuffle/repeat, etc.)\n- **Netease music search/playlists/likes/lyrics** (via external `NeteaseCloudMusicApi`)\n- **QQ Music search/playlists/lyrics/play URLs** (built into backend; login-required features can be configured from the web console)\n- **Web console** (Vue 3 frontend for search/queue/lyrics/settings)\n\n![Preview](docs/1.png)\n![Preview](docs/2.png)\n![Preview](docs/3.png)\n![Preview](docs/4.png)\n![Preview](docs/5.png)\n\n## Why TSBot (Pain Points and Goals)\n\nThis project aims to solve the \"dependency hell\" and maintainability issues of older setups.\n\nA common old stack looked like this:\n\n- `TS3AudioBot`\n- `NeteaseCloudMusicApi`\n- `TS3AudioBot-NetEaseCloudmusic-plugin`\n\nIn practice, this stack often suffers from:\n\n- **Heavy coupling**: the three pieces are tightly bound by versions, interfaces, and runtime assumptions, making deployment and troubleshooting expensive.\n- **Hard API replacement/updates**: Netease-related APIs change frequently, and replacing/upgrading API logic can cascade into bot core or plugin code.\n- **Critical plugin disappearance**: if `TS3AudioBot-NetEaseCloudmusic-plugin` becomes unavailable, the whole chain breaks and can no longer be maintained.\n\nTSBot redraws those boundaries:\n\n- **Voice and business logic are decoupled**: `voice-service` only handles \"connect to TeamSpeak + play audio\", exposing a stable gRPC control surface.\n- **Netease is a replaceable dependency**: backend talks to external `NeteaseCloudMusicApi` through `TSBOT_NETEASE_API_BASE`; future replacements/upgrades are largely isolated in backend adapters.\n- **Maintainable and evolvable architecture**: frontend/backend/voice-service can iterate independently, reducing single-point breakage.\n\nThe project has 3 components:\n\n- **backend/**: Python/FastAPI backend (queue/search/Netease + QQ Music integration/voice control)\n- **voice-service/**: Rust voice service (TeamSpeak connection + audio playback, exposes gRPC to backend)\n- **web/**: Vue 3 + Vite frontend (web console/player UI)\n\nMore docs:\n\n- `HOWTOSTART.md` (deployment/run guide)\n- `LOGGING.md` (unified logging system)\n- `web/README.md` (frontend details)\n\n## System Requirements\n\n- **Linux** (Ubuntu 20.04+ recommended)\n- **Python**: 3.8+\n- **Node.js**: 16+\n- **Rust**: 1.70+ (for `voice-service`)\n\nMusic source dependency notes:\n\n- **NeteaseCloudMusicApi** (required only for Netease features; self-hosted HTTP service)\n- **QQ Music** (built into backend; user playlists and more stable song URLs usually require an admin QQ Music cookie)\n\n## Architecture Overview\n\n```text\n   [web (Vue3)]  \u003c--HTTP--\u003e  [backend (FastAPI)]  \u003c--gRPC--\u003e  [voice-service (Rust)]  --\u003e  TeamSpeak (TS3/TS6)\n                                 |\n                                 | HTTP\n                                 v\n                        [NeteaseCloudMusicApi]\n```\n\n## TeamSpeak / TS6 Support\n\n- The `voice-service` primary client connection path already supports TeamSpeak login, channel join, text messaging, and audio playback against TS3/TS6 servers.\n- For backward compatibility, env vars still use the `TSBOT_TS3_*` naming scheme, even when connecting to TS6.\n- The code still contains an optional legacy `ServerQuery` fallback used only for old-style `client_description` updates; it is not the TS6 HTTP(S) Query interface.\n\n## Netease Support (Optional, via `NeteaseCloudMusicApi`)\n\nThis project does **not** directly call Netease official APIs. Instead, it forwards through your own `NeteaseCloudMusicApi` deployment.\n\n- **NPM**: https://www.npmjs.com/package/NeteaseCloudMusicApi\n- **Docs**: https://neteasecloudmusicapi.js.org/#/\n\nAfter deployment, set `TSBOT_NETEASE_API_BASE` to the service URL (for example, `http://127.0.0.1:3000/`).\n\nCommon deployment options (choose one, exact args follow upstream docs):\n\n```bash\n# Option A: start directly with npx\nnpx NeteaseCloudMusicApi@latest\n\n# Option B: use Docker (common image: binaryify/neteasecloudmusicapi)\n# docker run -d --name ncm-api -p 3000:3000 binaryify/neteasecloudmusicapi\n```\n\nIt is recommended to deploy this service where **backend can reach it** (same host `127.0.0.1:3000` or an internal network address).\n\n## QQ Music Support (Built-in)\n\nQQ Music support is provided directly by the backend; you do not need to deploy a separate QQ Music API service.\n\n- Search, song details, playlists, lyrics, album/artist/MV information are already exposed by backend endpoints.\n- Play URLs, user playlists, and other login-required features usually need an admin QQ Music cookie.\n- Admins can scan a QR code in the web console, or call `/admin/qqmusic/*` APIs to store/confirm the cookie.\n\n## Quick Start (Recommended)\n\n### 1) Configure Environment Variables\n\nCopy the template and edit:\n\n```bash\ncp tsbot.env.example tsbot.env\n```\n\nAt minimum, set:\n\n- `TSBOT_TS3_HOST` / `TSBOT_TS3_PORT` / `TSBOT_TS3_CHANNEL_ID` (TeamSpeak connection settings; historical `TSBOT_TS3_*` naming is retained)\n- `TSBOT_COOKIE_KEY` (used to encrypt stored admin cookies; use your own random string)\n\nDepending on music source:\n\n- For Netease: set `TSBOT_NETEASE_API_BASE` to your `NeteaseCloudMusicApi` URL, for example `http://127.0.0.1:3000/`\n- For QQ Music login-required features: store the admin QQ Music cookie via the web console or `/admin/qqmusic/*` APIs\n\nOptional:\n\n- `TSBOT_TS3_SERVER_PASSWORD` / `TSBOT_TS3_CHANNEL_PASSWORD` / `TSBOT_TS3_CHANNEL_PATH`\n- `TSBOT_TS3_IDENTITY` / `TSBOT_TS3_IDENTITY_FILE` / `TSBOT_TS3_AVATAR_DIR`\n- `TSBOT_ADMIN_TOKEN`: enable backend admin endpoint protection (request header `x-admin-token`)\n- `TSBOT_WEB_HOST` / `TSBOT_WEB_PORT`: frontend production preview bind host/port (used by `run-web.sh` / `nohup-start.sh`)\n- `TSBOT_WEB_API_PROXY_TARGET`: proxy target for frontend dev / preview mode (defaults to `TSBOT_HOST` / `TSBOT_PORT`)\n- `TSBOT_WEB_ALLOWED_HOSTS`: comma-separated host allowlist when you access Vite dev / preview through a domain\n- `VITE_DEV_HOST` / `VITE_DEV_PORT`: frontend dev server bind host/port\n- `VITE_API_BASE`: frontend backend base URL (recommended default `/api`, forwarded by dev / preview / Docker reverse proxy)\n\n### 2) Install Dependencies\n\nBackend (Python):\n\n```bash\ncd backend\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\ncd ..\n```\n\nFrontend (Node):\n\n```bash\ncd web\nnpm install\ncd ..\n```\n\nVoice service (Rust):\n\n```bash\n# Install Rust if not installed\n# https://rustup.rs/\n\n# Build voice-service\nmake voice-build\n```\n\nYou can also use the convenience targets added to the repository:\n\n```bash\nmake backend-setup\nmake web-build\nmake all\n```\n\n### 3) Foreground Startup (production-style)\n\nRun in 3 terminals:\n\n```bash\n./run-voicemake.sh\n```\n\n```bash\n./run-backend.sh\n```\n\n```bash\n./run-web.sh\n```\n\nThese scripts automatically read root `tsbot.env`. `run-web.sh` now builds the frontend bundle first, then serves it with `vite preview` on `TSBOT_WEB_PORT` (default `8080`).\n\n### 4) One-Command Startup (`nohup`, recommended for remote servers)\n\n```bash\nchmod +x ./nohup-start.sh ./nohup-stop.sh ./nohup-status.sh\n\n# Start (launches voice/backend/web and writes logs to logs/)\n./nohup-start.sh\n\n# Check status (ports + log paths)\n./nohup-status.sh\n\n# Stop\n./nohup-stop.sh\n```\n\n### 5) Local Development Startup (with reload / dev server)\n\nRun in 3 terminals:\n\n```bash\n./run-voicemake.sh\n```\n\n```bash\nbackend/.venv/bin/uvicorn backend.main:app --reload --reload-exclude \"backend/_generated/*\" --host 127.0.0.1 --port 8009\n```\n\n```bash\nnpm --prefix web run dev\n```\n\nLocal development uses `http://127.0.0.1:5173` by default and proxies `/api` to the backend.\n\n## Docker Deployment\n\nThe repository now includes:\n\n- `docker-compose.yml`\n- `docker-compose.prebuilt.yml`\n- `Dockerfile.backend`\n- `Dockerfile.voice-service`\n- `Dockerfile.web`\n\n### 1) Prepare env file\n\n```bash\ncp tsbot.env.example tsbot.env\n```\n\nIf your `NeteaseCloudMusicApi` runs on the host machine, set:\n\n- `TSBOT_NETEASE_API_BASE=http://host.docker.internal:3000/`\n\n### 2) Build and run\n\n```bash\ndocker compose up -d --build\n```\n\n### 3) Inspect\n\n```bash\ndocker compose ps\ndocker compose logs -f backend\ndocker compose logs -f web\n```\n\n### 4) Stop\n\n```bash\ndocker compose down\n```\n\nCompose starts 3 services by default:\n\n- `voice-service` (`50051`)\n- `backend` (`8009`)\n- `web` (`8080`, Nginx serves the production frontend bundle and reverse-proxies `/api/*` to backend)\n\n### 5) Use published images directly (Docker Hub / GHCR)\n\nIf you do not want to build locally, you can consume the prebuilt images published by GitHub Actions. The repository also ships `docker-compose.prebuilt.yml`, which pulls the official Docker Hub images by default:\n\n```bash\n# Docker Hub (default latest)\ndocker compose -f docker-compose.prebuilt.yml up -d\n\n# Pin a release tag, for example v0.4.0\nTSBOT_IMAGE_TAG=v0.4.0 docker compose -f docker-compose.prebuilt.yml up -d\n\n# Switch to GHCR\nTSBOT_IMAGE_REGISTRY=ghcr.io \\\nTSBOT_IMAGE_NAMESPACE=yichen11818 \\\ndocker compose -f docker-compose.prebuilt.yml up -d\n```\n\nImage naming format (the Docker Hub namespace is `yumi118`; the current GitHub Packages / GHCR owner is `yichen11818`; forks can override via env vars):\n\n- `docker.io/\u003cnamespace\u003e/neteasetsbot-backend:\u003ctag\u003e`\n- `docker.io/\u003cnamespace\u003e/neteasetsbot-web:\u003ctag\u003e`\n- `docker.io/\u003cnamespace\u003e/neteasetsbot-voice-service:\u003ctag\u003e`\n- `ghcr.io/\u003cowner\u003e/neteasetsbot-backend:\u003ctag\u003e`\n- `ghcr.io/\u003cowner\u003e/neteasetsbot-web:\u003ctag\u003e`\n- `ghcr.io/\u003cowner\u003e/neteasetsbot-voice-service:\u003ctag\u003e`\n\nNotes:\n\n- GitHub **Packages** only shows GHCR packages, so it stays empty if you only push to Docker Hub.\n- Seeing **3 image repositories** is expected because the project publishes `backend`, `web`, and `voice-service` separately.\n- GitHub **Releases** also includes `tsbot-\u003cversion\u003e-linux-amd64.tar.gz` and `SHA256SUMS.txt`; those are downloadable bundles, not container images.\n\n## Default Ports\n\n- **voice-service gRPC**: `127.0.0.1:50051`\n- **backend**: `127.0.0.1:8009` (`TSBOT_PORT`)\n- **web (production / Docker / run-web.sh)**: `127.0.0.1:8080` (`TSBOT_WEB_PORT`)\n- **web (local dev server)**: `127.0.0.1:5173` (`VITE_DEV_PORT`)\n\nBackend OpenAPI docs:\n\n- `http://127.0.0.1:8009/docs`\n\n## Admin Login State (Netease / QQ Music)\n\n### Netease Cookie\n\nBackend encrypts and stores the \"admin Netease cookie\" in database (`tsbot.db`) for:\n\n- getting more stable song URLs (avoid anonymous restrictions on some endpoints)\n- accessing features requiring login state (playlists, likes, etc.)\n\nSetup APIs (if admin token is enabled, include header `x-admin-token: \u003cTSBOT_ADMIN_TOKEN\u003e`):\n\n- `POST /admin/cookie`: store cookie\n- `GET /admin/status`: check if cookie exists\n- `GET /admin/account`: verify cookie validity\n\nThe frontend also provides a setup UI (see `web/README.md`).\n\n### QQ Music Cookie\n\nBackend also encrypts and stores the \"admin QQ Music cookie\" in database (`tsbot.db`) for:\n\n- getting more stable QQ Music play URLs\n- accessing login-required features such as user playlists and account info\n\nSetup APIs (if admin token is enabled, include header `x-admin-token: \u003cTSBOT_ADMIN_TOKEN\u003e`):\n\n- `GET /admin/qqmusic/status`: check if cookie exists\n- `POST /admin/qqmusic/cookie`: store cookie manually\n- `POST /admin/qqmusic/qr/confirm`: confirm QR login from the web UI and persist the cookie\n\nThe web console includes a QQ Music QR login flow.\n\n## Logging\n\nLogs are written to `logs/` by default:\n\n- `logs/backend.log`\n- `logs/voice.log`\n- `logs/web.log`\n\nSee `LOGGING.md` for details (`scripts/log-viewer.sh` / `scripts/unified-logger.sh`).\n\n## Project Structure\n\n```text\n.\n├── backend/         # FastAPI backend\n├── web/             # Vue3 frontend\n├── voice-service/   # Rust voice service (gRPC + TeamSpeak)\n├── proto/           # gRPC proto definitions\n├── data/            # runtime data/config (e.g. config.json)\n├── logs/            # runtime logs (created by startup scripts)\n├── HOWTOSTART.md\n├── LOGGING.md\n└── tsbot.env.example\n```\n\n## FAQ\n\n- **Is the web port 5173 or 8080?**\n  - `5173` is the local Vite dev server (`npm --prefix web run dev` / `VITE_DEV_PORT`)\n  - `8080` is the production foreground and Docker default (`run-web.sh` / `nohup-start.sh` / `TSBOT_WEB_PORT`)\n\n- **Frontend request errors / cannot reach backend?**\n  - Recommended default is `VITE_API_BASE=/api`, which is reverse-proxied by dev server / preview / Docker Nginx to backend\n  - If you do not use same-origin proxying, set `VITE_API_BASE` explicitly or point `TSBOT_WEB_API_PROXY_TARGET` at the backend\n\n- **Seeing a Vite host security error when accessing via domain?**\n  - That is Vite host validation working as designed.\n  - Set `TSBOT_WEB_ALLOWED_HOSTS=\"dev.example.com,.example.com\"` in `tsbot.env` and only whitelist the domains you really need.\n\n- **Backend cannot reach voice-service?**\n  - Check `TSBOT_VOICE_GRPC_ADDR` is `127.0.0.1:50051`\n  - Ensure `make voice-run` or `run-voicemake.sh` is running\n\n- **Is TS6 fully supported?**\n  - The primary client connection already supports TS6, while configuration still uses the historical `TSBOT_TS3_*` names.\n  - Legacy `TSBOT_TS3_SERVERQUERY_*` settings still map to the old ServerQuery fallback, not TS6 HTTP(S) Query.\n\n## License\n\nSee `LICENSE`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyichen11818%2Fneteasetsbot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyichen11818%2Fneteasetsbot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyichen11818%2Fneteasetsbot/lists"}