From 10da6c91a3bf7bc26a2e91df2cb53a7516e833f8 Mon Sep 17 00:00:00 2001 From: arch3rPro Date: Thu, 14 May 2026 00:47:03 +0800 Subject: [PATCH] feat(lxserver): add LXServer app package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增LXServer音乐同步服务器与Web播放器应用包,包含v1.9.1和latest两个版本的部署配置、应用信息说明文档以及logo资源。 --- apps/lxserver/1.9.1/data.yml | 73 ++++++++++++++++++++++++ apps/lxserver/1.9.1/docker-compose.yml | 28 +++++++++ apps/lxserver/README.md | 59 +++++++++++++++++++ apps/lxserver/README_en.md | 59 +++++++++++++++++++ apps/lxserver/data.yml | 29 ++++++++++ apps/lxserver/latest/data.yml | 73 ++++++++++++++++++++++++ apps/lxserver/latest/docker-compose.yml | 28 +++++++++ apps/lxserver/logo.png | Bin 0 -> 11819 bytes 8 files changed, 349 insertions(+) create mode 100644 apps/lxserver/1.9.1/data.yml create mode 100644 apps/lxserver/1.9.1/docker-compose.yml create mode 100644 apps/lxserver/README.md create mode 100644 apps/lxserver/README_en.md create mode 100644 apps/lxserver/data.yml create mode 100644 apps/lxserver/latest/data.yml create mode 100644 apps/lxserver/latest/docker-compose.yml create mode 100644 apps/lxserver/logo.png diff --git a/apps/lxserver/1.9.1/data.yml b/apps/lxserver/1.9.1/data.yml new file mode 100644 index 0000000..b99b5dd --- /dev/null +++ b/apps/lxserver/1.9.1/data.yml @@ -0,0 +1,73 @@ +additionalProperties: + formFields: + - default: "9527" + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Service Port + labelZh: 服务端口 + required: true + rule: paramPort + type: number + label: + en: Service Port + zh: 服务端口 + - default: "123456" + edit: true + envKey: FRONTEND_PASSWORD + labelEn: Admin Password + labelZh: 管理后台密码 + required: false + rule: paramCommon + type: password + label: + en: Admin Password + zh: 管理后台密码 + - default: "false" + edit: true + envKey: ENABLE_WEBPLAYER_AUTH + labelEn: Enable Player Auth + labelZh: 启用播放器访问密码 + required: false + rule: paramCommon + type: select + values: + - label: "True" + value: "true" + - label: "False" + value: "false" + label: + en: Enable Player Auth + zh: 启用播放器访问密码 + - default: "123456" + edit: true + envKey: WEBPLAYER_PASSWORD + labelEn: Player Password + labelZh: 播放器访问密码 + required: false + rule: paramCommon + type: password + label: + en: Player Password + zh: 播放器访问密码 + - default: "/music" + edit: true + envKey: PLAYER_PATH + labelEn: Player Path + labelZh: 播放器访问路径 + required: false + rule: paramCommon + type: text + label: + en: Player Path + zh: 播放器访问路径 + - default: "Asia/Shanghai" + edit: true + envKey: TZ + labelEn: Time Zone + labelZh: 时区 + required: true + rule: paramCommon + type: text + label: + en: Time Zone + zh: 时区 diff --git a/apps/lxserver/1.9.1/docker-compose.yml b/apps/lxserver/1.9.1/docker-compose.yml new file mode 100644 index 0000000..f5f92e2 --- /dev/null +++ b/apps/lxserver/1.9.1/docker-compose.yml @@ -0,0 +1,28 @@ +services: + lxserver: + image: xcq0607/lxserver:v1.9.1 + container_name: ${CONTAINER_NAME} + restart: always + networks: + - 1panel-network + ports: + - "${PANEL_APP_PORT_HTTP}:9527" + volumes: + - ./data:/server/data + - ./logs:/server/logs + - ./cache:/server/cache + - ./music:/server/music + environment: + - TZ=Asia/Shanghai + - NODE_ENV=production + - PORT=9527 + - FRONTEND_PASSWORD=${FRONTEND_PASSWORD} + - ENABLE_WEBPLAYER_AUTH=${ENABLE_WEBPLAYER_AUTH} + - WEBPLAYER_PASSWORD=${WEBPLAYER_PASSWORD} + - PLAYER_PATH=${PLAYER_PATH} + - TZ=${TZ} + labels: + createdBy: "Apps" +networks: + 1panel-network: + external: true diff --git a/apps/lxserver/README.md b/apps/lxserver/README.md new file mode 100644 index 0000000..3558184 --- /dev/null +++ b/apps/lxserver/README.md @@ -0,0 +1,59 @@ +# LXServer + +LX Music Sync Server 增强版,一个基于 Node.js 的音乐同步服务器和 Web 播放器。 + +## 功能特点 + +- 现代化 Web 播放器,支持深色模式和多套主题皮肤 +- 多源聚合搜索,支持各大音乐平台资源搜索与播放 +- 全平台数据同步,完美适配 LX Music 桌面端与移动端 +- Subsonic 协议支持,可配合音流、Feishin 等第三方客户端 +- 全自动化缓存系统,自动保存歌词、链接及歌曲文件 +- 歌词卡片分享功能,支持生成精美歌词海报 +- 访问控制,支持播放器访问密码和管理员/用户权限管理 +- 支持导入自定义音乐源脚本 + +## 使用说明 + +### 默认端口 + +- Web 播放器: 9527 +- 管理后台: 9527 + +### 访问地址 + +- Web 播放器: http://your-ip:9527/music (可通过 `PLAYER_PATH` 修改) +- 同步管理后台: http://your-ip:9527 (可通过 `ADMIN_PATH` 修改) + +### 默认账号密码 + +- 管理后台默认密码: 123456 (部署后请立即修改) + +### 数据目录 + +应用数据存储在以下目录: + +- `./data`: 同步快照、用户信息和系统设置核心数据 +- `./logs`: 系统运行日志 +- `./cache`: Web 播放器自动化缓存文件 +- `./music`: 本地音乐库目录 + +## 环境变量配置 + +| 环境变量 | 说明 | 默认值 | +|---------|------|--------| +| FRONTEND_PASSWORD | Web 管理界面访问密码 | 123456 | +| ENABLE_WEBPLAYER_AUTH | 是否启用 Web 播放器访问密码 | false | +| WEBPLAYER_PASSWORD | Web 播放器访问密码 | 123456 | +| PLAYER_PATH | Web 播放器访问路径 | /music | +| ADMIN_PATH | 后台管理界面访问路径 | (空) | +| DISABLE_TELEMETRY | 是否禁用匿名数据统计 | false | +| SUBSONIC_ENABLE | 是否启用 Subsonic 协议支持 | true | +| SUBSONIC_PATH | Subsonic API 访问路径 | /rest | + +## 相关链接 + +- 官方网站: https://xcq0607.github.io/lxserver/ +- GitHub: https://github.com/XCQ0607/lxserver +- 文档: https://xcq0607.github.io/lxserver/ +- Docker Hub: https://hub.docker.com/r/xcq0607/lxserver diff --git a/apps/lxserver/README_en.md b/apps/lxserver/README_en.md new file mode 100644 index 0000000..0c6889c --- /dev/null +++ b/apps/lxserver/README_en.md @@ -0,0 +1,59 @@ +# LXServer + +LX Music Sync Server Enhanced Edition, a Node.js-based music sync server and web player. + +## Features + +- Modern web player with dark mode and multiple theme skins +- Multi-source aggregated search supporting major music platforms +- Cross-platform data synchronization for LX Music desktop and mobile +- Subsonic protocol support for third-party clients like Yinliu, Feishin +- Fully automated caching system for lyrics, links, and audio files +- Lyrics card sharing feature with customizable poster generation +- Access control with player password and admin/user permissions +- Support for importing custom music source scripts + +## Usage + +### Default Ports + +- Web Player: 9527 +- Admin Console: 9527 + +### Access URLs + +- Web Player: http://your-ip:9527/music (configurable via `PLAYER_PATH`) +- Admin Console: http://your-ip:9527 (configurable via `ADMIN_PATH`) + +### Default Credentials + +- Admin Console Default Password: 123456 (change immediately after deployment) + +### Data Directories + +Application data is stored in the following directories: + +- `./data`: Sync snapshots, user information, and system settings +- `./logs`: System runtime logs +- `./cache`: Web player automated cache files +- `./music`: Local music library directory + +## Environment Variables + +| Variable | Description | Default | +|----------|-------------|---------| +| FRONTEND_PASSWORD | Web admin interface password | 123456 | +| ENABLE_WEBPLAYER_AUTH | Enable web player password | false | +| WEBPLAYER_PASSWORD | Web player access password | 123456 | +| PLAYER_PATH | Web player access path | /music | +| ADMIN_PATH | Admin console access path | (empty) | +| DISABLE_TELEMETRY | Disable anonymous telemetry | false | +| SUBSONIC_ENABLE | Enable Subsonic protocol support | true | +| SUBSONIC_PATH | Subsonic API access path | /rest | + +## Links + +- Website: https://xcq0607.github.io/lxserver/ +- GitHub: https://github.com/XCQ0607/lxserver +- Documentation: https://xcq0607.github.io/lxserver/ +- Docker Hub: https://hub.docker.com/r/xcq0607/lxserver diff --git a/apps/lxserver/data.yml b/apps/lxserver/data.yml new file mode 100644 index 0000000..81e9923 --- /dev/null +++ b/apps/lxserver/data.yml @@ -0,0 +1,29 @@ +name: LXServer +tags: + - 音乐 + - 媒体 +title: LXServer +description: LX Music 数据同步服务器与 Web 播放器 +additionalProperties: + key: lxserver + name: LXServer + tags: + - Music + - Media + shortDescZh: LX Music 数据同步服务器与 Web 播放器 + shortDescEn: LX Music data sync server and web player + description: + zh: LX Music Sync Server 是一个基于 Node.js 的音乐同步服务器和 Web 播放器,支持多端数据同步、自定义音乐源、Subsonic 协议兼容、现代化 Web 播放器等功能。 + en: LX Music Sync Server is a Node.js-based music sync server and web player, supporting multi-device sync, custom music sources, Subsonic protocol compatibility, and modern web playback. + type: website + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://xcq0607.github.io/lxserver/ + github: https://github.com/XCQ0607/lxserver + document: https://xcq0607.github.io/lxserver/ + architectures: + - amd64 + - arm64 + - arm/v7 + - "386" diff --git a/apps/lxserver/latest/data.yml b/apps/lxserver/latest/data.yml new file mode 100644 index 0000000..b99b5dd --- /dev/null +++ b/apps/lxserver/latest/data.yml @@ -0,0 +1,73 @@ +additionalProperties: + formFields: + - default: "9527" + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Service Port + labelZh: 服务端口 + required: true + rule: paramPort + type: number + label: + en: Service Port + zh: 服务端口 + - default: "123456" + edit: true + envKey: FRONTEND_PASSWORD + labelEn: Admin Password + labelZh: 管理后台密码 + required: false + rule: paramCommon + type: password + label: + en: Admin Password + zh: 管理后台密码 + - default: "false" + edit: true + envKey: ENABLE_WEBPLAYER_AUTH + labelEn: Enable Player Auth + labelZh: 启用播放器访问密码 + required: false + rule: paramCommon + type: select + values: + - label: "True" + value: "true" + - label: "False" + value: "false" + label: + en: Enable Player Auth + zh: 启用播放器访问密码 + - default: "123456" + edit: true + envKey: WEBPLAYER_PASSWORD + labelEn: Player Password + labelZh: 播放器访问密码 + required: false + rule: paramCommon + type: password + label: + en: Player Password + zh: 播放器访问密码 + - default: "/music" + edit: true + envKey: PLAYER_PATH + labelEn: Player Path + labelZh: 播放器访问路径 + required: false + rule: paramCommon + type: text + label: + en: Player Path + zh: 播放器访问路径 + - default: "Asia/Shanghai" + edit: true + envKey: TZ + labelEn: Time Zone + labelZh: 时区 + required: true + rule: paramCommon + type: text + label: + en: Time Zone + zh: 时区 diff --git a/apps/lxserver/latest/docker-compose.yml b/apps/lxserver/latest/docker-compose.yml new file mode 100644 index 0000000..44b0b2a --- /dev/null +++ b/apps/lxserver/latest/docker-compose.yml @@ -0,0 +1,28 @@ +services: + lxserver: + image: xcq0607/lxserver:latest + container_name: ${CONTAINER_NAME} + restart: always + networks: + - 1panel-network + ports: + - "${PANEL_APP_PORT_HTTP}:9527" + volumes: + - ./data:/server/data + - ./logs:/server/logs + - ./cache:/server/cache + - ./music:/server/music + environment: + - TZ=Asia/Shanghai + - NODE_ENV=production + - PORT=9527 + - FRONTEND_PASSWORD=${FRONTEND_PASSWORD} + - ENABLE_WEBPLAYER_AUTH=${ENABLE_WEBPLAYER_AUTH} + - WEBPLAYER_PASSWORD=${WEBPLAYER_PASSWORD} + - PLAYER_PATH=${PLAYER_PATH} + - TZ=${TZ} + labels: + createdBy: "Apps" +networks: + 1panel-network: + external: true diff --git a/apps/lxserver/logo.png b/apps/lxserver/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f22d43e7e60ac5d58f505d3d1ca82a5f944a9420 GIT binary patch literal 11819 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