YesPlayMusic

repository·master·Indexed 12 days ago

https://github.com/qier222/yesplaymusic

A high-aesthetic third-party music player for NetEase Cloud Music. It supports web deployment via Vercel, Docker, and Replit, as well as an Electron-based desktop client for macOS, Windows, and Linux. Version 0.4.10 includes a comprehensive API for managing albums, artists, and authentication via phone, email, or QR code.

Tokens
12.9K
Snippets
63
Records
65
Agent score
99%

What's inside YesPlayMusic

  1. Build the Electron client manually

    master

    If a pre-built binary is not available for your architecture, you can build your own using Node.js and Yarn.

    1. Prerequisites: Install Node.js and Yarn (npm install -g yarn).
    2. Clone: git clone --recursive https://github.com/qier222/YesPlayMusic.git
    3. Setup:
      • yarn install
      • Copy .env.example to .env
    4. Build Commands:
    TargetCommand
    Windows 32-bityarn electron:build --windows nsis:ia32
    Windows ARMyarn electron:build --windows nsis:arm64
    Debian armv7l (Raspberry Pi)yarn electron:build --linux deb:armv7l
    macOS ARMyarn electron:build --macos dir:arm64

    Output files will be located in the /dist_electron directory.

    yarn electron:build --windows nsis:ia32
  2. Install YesPlayMusic Desktop Client

    master

    YesPlayMusic provides an Electron-based desktop client for macOS, Windows, and Linux. You can download pre-built installation packages from the Releases page or use package managers:

    • macOS: Use Homebrew
      brew install --cask yesplaymusic
    • Windows: Use Scoop
      scoop install extras/yesplaymusic
    brew install --cask yesplaymusic
  3. Configure the local development environment

    master

    To develop or run the project locally, follow these steps:

    1. Install Dependencies:
      yarn install
    2. **Environment Setup**: 
     ```bash
     cp .env.example .env
    1. Run Web Version:
      yarn serve
    4. **Run Electron Version**: 
     ```bash
    yarn electron:serve
    1. Run Local API (Optional, defaults to port 3000):
      yarn netease_api:run
    yarn install
    cp .env.example .env
    yarn serve
  4. Deploy YesPlayMusic via Docker

    master

    You can containerize YesPlayMusic using Docker or Docker Compose.

    Build and Run with Docker:

    docker build -t yesplaymusic .
    docker run -d --name YesPlayMusic -p 80:80 yesplaymusic

    Run with Docker Compose:

    docker-compose up -d

    After running, the application will be available at http://localhost.

    docker build -t yesplaymusic .
    docker run -d --name YesPlayMusic -p 80:80 yesplaymusic
  5. Deploy YesPlayMusic to Vercel

    master

    You can host the web version of YesPlayMusic on Vercel. This requires a deployed instance of the NeteaseCloudMusicApi.

    1. Deploy API: Ensure you have a Netease API endpoint available.
    2. Fork Repository: Fork this repository to your GitHub account.
    3. Configure Rewrites: Create a vercel.json file in the root of your fork to proxy API requests. Replace https://your-netease-api.example.com with your actual API URL:
      {
        "rewrites": [
          {
            "source": "/api/:match*",
            "destination": "https://your-netease-api.example.com/:match*"
          }
        ]
      }
    4. Import to Vercel: Log in to Vercel, import your forked repository.
    5. Set Environment Variables: In the Vercel project settings, add the following environment variable:
      • Name: VUE_APP_NETEASE_API_URL
      • Value: /api
    6. Deploy: Click Deploy.
    {
      "rewrites": [
        {
          "source": "/api/:match*",
          "destination": "https://your-netease-api.example.com/:match*"
        }
      ]
    }
  6. Deploy YesPlayMusic to Replit

    master
    1. Create a new Repl using the Bash template.
    2. Run the installation script in the Replit shell:
      bash <(curl -s -L https://raw.githubusercontent.com/qier222/YesPlayMusic/main/install-replit.sh)
    3. If the build fails due to Replit's memory limits (1GB/3GB), run the following manually:
     ```bash
     cd /home/runner/${REPL_SLUG}/music && yarn install && yarn run build
    1. Use the green Run button to start the application.
    bash <(curl -s -L https://raw.githubusercontent.com/qier222/YesPlayMusic/main/install-replit.sh)
  7. Deploy YesPlayMusic to your own server

    master

    To host the web version on your own infrastructure:

    1. Deploy API: Set up NeteaseCloudMusicApi.
    2. Clone Repository:
      git clone --recursive https://github.com/qier222/YesPlayMusic.git
    3. Install Dependencies:
      yarn install
    4. Configure Environment: Copy .env.example to .env. Set VUE_APP_NETEASE_API_URL to your API address.
      • If using a reverse proxy (e.g., Nginx) to map the API to /api, use /api.
      • For local development, use http://localhost:3000 (or your API port).
    5. Build:
      yarn run build
    6. Deploy: Upload the contents of the /dist directory to your web server.
    git clone --recursive https://github.com/qier222/YesPlayMusic.git
    yarn install
    yarn run build
  8. Deploy YesPlayMusic using Docker Compose

    master

    You can deploy the YesPlayMusic stack using Docker Compose. The setup includes the main YesPlayMusic service and an UnblockNeteaseMusic service to handle music unblocking.

    Key Configuration Details:

    • Ports: The main service maps port 80 of the container to port 80 of the host.
    • Volumes: The configuration expects a local Nginx configuration file at ./docker/nginx.conf.example to be mounted to /etc/nginx/conf.d/default.conf inside the container.
    • Environment Variables: The YesPlayMusic service includes NODE_TLS_REJECT_UNAUTHORIZED=0 to handle SSL certificate issues.
    • Dependencies: YesPlayMusic depends on the UnblockNeteaseMusic service being running.
    services:
      YesPlayMusic:
        build:
          context: .
        image: yesplaymusic
        container_name: YesPlayMusic
        volumes:
          - /etc/localtime:/etc/localtime:ro
          - /etc/timezone:/etc/timezone:ro
          - ./docker/nginx.conf.example:/etc/nginx/conf.d/default.conf:ro
        ports:
          - 80:80
        restart: always
        depends_on:
          - UnblockNeteaseMusic
        environment:
          - NODE_TLS_REJECT_UNAUTHORIZED=0
        networks:
          my_network:
    
      UnblockNeteaseMusic:
        image: pan93412/unblock-netease-music-enhanced
        command: -o kugou kuwo migu bilibili pyncmd -p 80:443 -f 45.127.129.53 -e -
        networks:
          my_network:
            aliases:
              - music.163.com
              - interface.music.163.com
              - interface3.music.163.com
              - interface.music.163.com.163jiasu.com
              - interface3.music.163.com.163jiasu.com
        restart: always
    
    networks:
      my_network:
        driver: bridge
  9. Authenticate via QR Code

    master

    The QR code authentication process follows a three-step lifecycle:

    1. Generate Key: Call loginQrCodeKey() to obtain a unique key.
    2. Create QR Code: Call loginQrCodeCreate({ key, qrimg: true }) using the key from step 1. If qrimg is passed, the response will include a base64 encoded image of the QR code. Otherwise, you can use the returned QR information to render the code yourself using a third-party library.
    3. Poll Status: Call loginQrCodeCheck(key) periodically to monitor the scan status.

    Status Codes for loginQrCodeCheck:

    • 800: QR code expired.
    • 801: Waiting for scan.
    • 802: Waiting for user confirmation.
    • 803: Authorized and login successful (the response will contain the session cookies).
    // 1. Get key
    const { data: { key } } = await loginQrCodeKey();
    
    // 2. Create QR (requesting base64 image)
    const { data: qrData } = await loginQrCodeCreate({ key, qrimg: true });
    // Use qrData.qrimg to display the image
    
    // 3. Poll status
    const checkInterval = setInterval(async () => {
      const { data: status } = await loginQrCodeCheck(key);
      if (status.code === 803) {
        console.log('Login successful, cookies received');
        clearInterval(checkInterval);
      } else if (status.code === 800) {
        console.log('QR code expired');
        clearInterval(checkInterval);
      }
    }, 2000);
  10. Configure the Dev Server proxy and port

    master

    The devServer configuration allows you to set the development port and proxy API requests. By default, it uses the DEV_SERVER_PORT environment variable or falls back to 8080. It includes a proxy rule for /api that redirects to http://localhost:3000 and rewrites the path by removing the /api prefix.

    devServer: {
      disableHostCheck: true,
      port: process.env.DEV_SERVER_PORT || 8080,
      proxy: {
        '^/api': {
          target: 'http://localhost:3000',
          changeOrigin: true,
          pathRewrite: {
            '^/api': '/',
          },
        },
      },
    }
  11. Configure PWA settings

    master

    The pwa object defines Progressive Web App properties, including the application name, icon paths, theme color, and manifest background color.

    pwa: {
      name: 'YesPlayMusic',
      iconPaths: {
        favicon32: 'img/icons/favicon-32x32.png',
      },
      themeColor: '#ffffff00',
      manifestOptions: {
        background_color: '#335eea',
      },
    }
  12. Customize Electron Main and Renderer process webpack chains

    master

    You can provide custom webpack configurations specifically for the Electron Main process or the Renderer process via chainWebpackMainProcess and chainWebpackRendererProcess. This is useful for defining global constants like IS_ELECTRON or setting up specific loaders/aliases for each process.

    pluginOptions: {
      electronBuilder: {
        // Configuration for the Main process
        chainWebpackMainProcess: config => {
          config.plugin('define').tap(args => {
            args[0]['IS_ELECTRON'] = true;
            return args;
          });
        },
        // Configuration for the Renderer process
        chainWebpackRendererProcess: config => {
          config.plugin('define').tap(args => {
            args[0]['IS_ELECTRON'] = true;
            return args;
          });
        }
      }
    }