Compare commits

..

No commits in common. "master" and "v0.3.5" have entirely different histories.

465 changed files with 36194 additions and 17844 deletions

View file

@ -1,16 +0,0 @@
node_modules
npm-debug.log
Dockerfile*
docker-compose*
.dockerignore
.git
.github
.gitignore
README.md
LICENSE
.vscode
dist
dist_electron
build
images
script

View file

@ -1,7 +1,5 @@
VUE_APP_NETEASE_API_URL=/api
VUE_APP_ELECTRON_API_URL=/api
VUE_APP_ELECTRON_API_URL_DEV=http://127.0.0.1:10754
VUE_APP_LASTFM_API_KEY=09c55292403d961aa517ff7f5e8a3d9c
VUE_APP_LASTFM_API_SHARED_SECRET=307c9fda32b3904e53654baff215cb67
VUE_APP_ELECTRON_API_URL_DEV=http://127.0.0.1:3000
VUE_APP_ENABLE_SENTRY=false
DEV_SERVER_PORT=20201

4
.envrc
View file

@ -1,4 +0,0 @@
source_url "https://raw.githubusercontent.com/cachix/devenv/82c0147677e510b247d8b9165c54f73d32dfd899/direnvrc" "sha256-7u4iDd1nZpxL4tCzmPG0dQgC5V+/44Ba+tHkPob1v2k="
export NIXPKGS_ALLOW_INSECURE=1
use devenv

View file

@ -1,15 +1,6 @@
name: Release
name: Build / Release
env:
YARN_INSTALL_NOPT: yarn add --ignore-platform --ignore-optional
on:
push:
branches:
- master
tags:
- v*
workflow_dispatch:
on: [push, pull_request]
jobs:
release:
@ -17,26 +8,23 @@ jobs:
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-22.04]
os: [macos-latest, windows-latest, ubuntu-16.04]
steps:
- name: Check out Git repository
uses: actions/checkout@v3
with:
submodules: "recursive"
uses: actions/checkout@v2
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v3
uses: actions/setup-node@v1
with:
node-version: 16
cache: 'yarn'
node-version: 14.16.0
- name: Install RPM & Pacman (on Ubuntu)
if: runner.os == 'Linux'
run: |
sudo apt-get update &&
sudo apt-get install --no-install-recommends -y rpm &&
sudo apt-get install --no-install-recommends -y libarchive-tools &&
sudo apt-get install --no-install-recommends -y bsdtar &&
sudo apt-get install --no-install-recommends -y libopenjp2-tools
- name: Install Snapcraft (on Ubuntu)
@ -45,47 +33,12 @@ jobs:
with:
snapcraft_token: ${{ secrets.snapcraft_token }}
- id: get_unm_version
name: Get the installed UNM version
run: |
yarn --ignore-optional
unm_version=$(node -e "console.log(require('./node_modules/@unblockneteasemusic/rust-napi/package.json').version)")
echo "::set-output name=unmver::${unm_version}"
shell: bash
- name: Install UNM dependencies for Windows
if: runner.os == 'Windows'
run: |
${{ env.YARN_INSTALL_NOPT }} \
@unblockneteasemusic/rust-napi-win32-x64-msvc@${{steps.get_unm_version.outputs.unmver}}
shell: bash
- name: Install UNM dependencies for macOS
if: runner.os == 'macOS'
run: |
${{ env.YARN_INSTALL_NOPT }} \
@unblockneteasemusic/rust-napi-darwin-x64@${{steps.get_unm_version.outputs.unmver}} \
@unblockneteasemusic/rust-napi-darwin-arm64@${{steps.get_unm_version.outputs.unmver}} \
dmg-license
shell: bash
- name: Install UNM dependencies for Linux
if: runner.os == 'Linux'
run: |
${{ env.YARN_INSTALL_NOPT }} \
@unblockneteasemusic/rust-napi-linux-x64-gnu@${{steps.get_unm_version.outputs.unmver}} \
@unblockneteasemusic/rust-napi-linux-arm64-gnu@${{steps.get_unm_version.outputs.unmver}} \
@unblockneteasemusic/rust-napi-linux-arm-gnueabihf@${{steps.get_unm_version.outputs.unmver}}
shell: bash
- name: Build/release Electron app
uses: samuelmeuli/action-electron-builder@v1.6.0
env:
VUE_APP_NETEASE_API_URL: /api
VUE_APP_ELECTRON_API_URL: /api
VUE_APP_ELECTRON_API_URL_DEV: http://127.0.0.1:10754
VUE_APP_LASTFM_API_KEY: 09c55292403d961aa517ff7f5e8a3d9c
VUE_APP_LASTFM_API_SHARED_SECRET: 307c9fda32b3904e53654baff215cb67
VUE_APP_ENABLE_SENTRY: false
with:
# GitHub token, automatically provided to the action
# (No need to define this secret in the repo settings)
@ -97,19 +50,19 @@ jobs:
use_vue_cli: true
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v2
with:
name: YesPlayMusic-mac
path: dist_electron/*-universal.dmg
if-no-files-found: ignore
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v2
with:
name: YesPlayMusic-win
path: dist_electron/*Setup*.exe
if-no-files-found: ignore
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v2
with:
name: YesPlayMusic-linux
path: dist_electron/*.AppImage

View file

@ -1,48 +0,0 @@
name: Upstream Sync
permissions:
contents: write
issues: write
actions: write
on:
schedule:
- cron: '0 * * * *' # every hour
workflow_dispatch:
jobs:
sync_latest_from_upstream:
name: Sync latest commits from upstream repo
runs-on: ubuntu-latest
if: ${{ github.event.repository.fork }}
steps:
- uses: actions/checkout@v4
- name: Clean issue notice
uses: actions-cool/issues-helper@v3
with:
actions: 'close-issues'
labels: '🚨 Sync Fail'
- name: Sync upstream changes
id: sync
uses: aormsby/Fork-Sync-With-Upstream-action@v3.4
with:
upstream_sync_repo: qier222/YesPlayMusic
upstream_sync_branch: master
target_sync_branch: master
target_repo_token: ${{ secrets.GITHUB_TOKEN }} # automatically generated, no need to set
test_mode: false
- name: Sync check
if: failure()
uses: actions-cool/issues-helper@v3
with:
actions: 'create-issue'
title: '🚨 同步失败 | Sync Fail'
labels: '🚨 Sync Fail'
body: |
Due to a change in the workflow file of the upstream repository, GitHub has automatically suspended the scheduled automatic update. You need to manually sync your fork.
由于上游仓库的 workflow 文件变更,导致 GitHub 自动暂停了本次自动更新,你需要手动 Sync Fork 一次。

13
.gitignore vendored
View file

@ -28,16 +28,3 @@ pnpm-debug.log*
/dist_electron
NeteaseCloudMusicApi-master
NeteaseCloudMusicApi-master.zip
# Local Netlify folder
.netlify
vercel.json
# Devenv
.devenv*
devenv.local.nix
# direnv
.direnv
# pre-commit
.pre-commit-config.yaml

4
.npmrc Normal file
View file

@ -0,0 +1,4 @@
# 如果发现 npm / yarn 安装太慢,可以解除注释
# registry=https://registry.npm.taobao.org/
# ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron
# phantomjs_cdnurl=https://npm.taobao.org/dist/phantomjs

1
.nvmrc
View file

@ -1 +0,0 @@
14

View file

@ -1,3 +1,5 @@
build
coverage
dist
netease_api

View file

@ -3,9 +3,10 @@
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"singleQuote": false,
"jsxSingleQuote": true,
"arrowParens": "avoid",
"jsxBracketSameLine": false,
"arrowParens": "always",
"endOfLine": "lf",
"bracketSpacing": true,
"htmlWhitespaceSensitivity": "strict"

View file

@ -1,25 +0,0 @@
FROM node:16.13.1-alpine as build
ENV VUE_APP_NETEASE_API_URL=/api
WORKDIR /app
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories &&\
apk add --no-cache python3 make g++ git
COPY package.json yarn.lock ./
RUN yarn install
COPY . .
RUN yarn config set electron_mirror https://npmmirror.com/mirrors/electron/ && \
yarn build
FROM nginx:1.20.2-alpine as app
COPY --from=build /app/package.json /usr/local/lib/
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories &&\
apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.14/main libuv \
&& apk add --no-cache --update-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.14/main nodejs npm \
&& npm i -g $(awk -F \" '{if($2=="NeteaseCloudMusicApi") print $2"@"$4}' /usr/local/lib/package.json) \
&& rm -f /usr/local/lib/package.json
COPY --from=build /app/docker/nginx.conf.example /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist /usr/share/nginx/html
CMD nginx ; exec npx NeteaseCloudMusicApi

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020-2023 qier222
Copyright (c) 2020 qier222
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

176
README.md
View file

@ -8,41 +8,31 @@
<p align="center">
高颜值的第三方网易云播放器
<br />
<a href="https://music.ineko.cc" target="blank"><strong>🌎 访问DEMO</strong></a>&nbsp;&nbsp;|&nbsp;&nbsp;
<a href="#%EF%B8%8F-安装" target="blank"><strong>📦️ 下载安装包</strong></a>&nbsp;&nbsp;|&nbsp;&nbsp;
<a href="https://t.me/yesplaymusic" target="blank"><strong>💬 加入交流群</strong></a>
<a href="https://music.qier222.com" target="blank"><strong>🌎 访问DEMO</strong></a>&nbsp;&nbsp;|&nbsp;&nbsp;
<a href="#%EF%B8%8F-安装" target="blank"><strong>📦️ 下载安装包</strong></a>
<br />
<br />
</p>
</p>
[![Library][library-screenshot]](https://music.ineko.cc)
## 全新版本
全新2.0 Alpha测试版已发布欢迎前往 [Releases](https://github.com/qier222/YesPlayMusic/releases) 页面下载。
当前版本将会进入维护模式除重大bug修复外不会再更新新功能。
[![Library][library-screenshot]](https://music.qier222.com)
## ✨ 特性
- ✅ 使用 Vue.js 全家桶开发
- 🔴 网易云账号登录(扫码/手机/邮箱登录)
- 🔴 网易云账号登录
- 📺 支持 MV 播放
- 📃 支持歌词显示
- 📻 支持私人 FM / 每日推荐歌曲
- 📻 支持私人 FM
- 🚫🤝 无任何社交功能
- 🌎️ 海外用户可直接播放(需要登录网易云账号)
- 🔐 支持 [UnblockNeteaseMusic](https://github.com/UnblockNeteaseMusic/server#音源清单),自动使用[各类音源](https://github.com/UnblockNeteaseMusic/server#音源清单)替换变灰歌曲链接 (网页版不支持)
- 「各类音源」指默认启用的音源。
- YouTube 音源需自行安装 `yt-dlp`
- 🔐 支持 [UnblockNeteaseMusic](https://github.com/nondanee/UnblockNeteaseMusic),自动使用 QQ/酷狗/酷我音源替换变灰歌曲链接 (网页版不支持)
- ⏭️ 支持 MediaSession API可以使用系统快捷键操作上一首下一首
- ✔️ 每日自动签到(手机端和电脑端同时签到)
- 🌚 Light/Dark Mode 自动切换
- 👆 支持 Touch Bar
- 🖥️ 支持 PWA可在 Chrome/Edge 里点击地址栏右边的 安装到电脑
- 🟥 支持 Last.fm Scrobble
- ☁️ 支持音乐云盘
- ⌨️ 自定义快捷键和全局快捷键
- 🎧 支持 Mpris
- 🙉 支持显示歌曲和专辑的 Explicit 标志
- 🛠 更多特性开发中
## 📦️ 安装
@ -50,131 +40,28 @@
Electron 版本由 [@hawtim](https://github.com/hawtim) 和 [@qier222](https://github.com/qier222) 适配并维护,支持 macOS、Windows、Linux。
访问本项目的 [Releases](https://github.com/qier222/YesPlayMusic/releases)
页面下载安装包。
页面下载安装包,或者访问 [镜像下载站 (大陆访问更快)](https://dl.qier222.com/YesPlayMusic/) 下载
- macOS 用户可以通过 Homebrew 来安装:`brew install --cask yesplaymusic`
- Windows 用户可以通过 Scoop 来安装:`scoop install extras/yesplaymusic`
macOS 用户也可以通过 `brew install --cask yesplaymusic` 来安装。
## ⚙️ 部署至 Vercel
除了下载安装包使用,你还可以将本项目部署到 Vercel 或你的服务器上。下面是部署到 Vercel 的方法。
本项目的 Demo (https://music.qier222.com) 就是部署在 Vercel 上的网站。
[![Powered by Vercel](https://www.datocms-assets.com/31049/1618983297-powered-by-vercel.svg)](https://vercel.com/?utm_source=ohmusic&utm_campaign=oss)
除了下载安装包使用,你还可以将本项目部署到 Vercel 或你的服务器上。下面是部署到 Vercel 的方法
1. 部署网易云 API详情参见 [Binaryify/NeteaseCloudMusicApi](https://neteasecloudmusicapi.vercel.app/#/?id=%e5%ae%89%e8%a3%85)
。你也可以将 API 部署到 Vercel。
2. 点击本仓库右上角的 Fork复制本仓库到你的 GitHub 账号。
3. 点击仓库的 Add File选择 Create new file输入 `vercel.json`,将下面的内容复制粘贴到文件中,并将 `https://your-netease-api.example.com` 替换为你刚刚部署的网易云 API 地址:
3. 打开 [Vercel.com](https://vercel.com),使用 GitHub 登录。
```json
{
"rewrites": [
{
"source": "/api/:match*",
"destination": "https://your-netease-api.example.com/:match*"
}
]
}
```
4. 点击 Import Git Repository 并选择你刚刚复制的仓库并点击 Import。
4. 打开 [Vercel.com](https://vercel.com),使用 GitHub 登录
5. 点击 PERSONAL ACCOUNT 旁边的 Select。
5. 点击 Import Git Repository 并选择你刚刚复制的仓库并点击 Import。
6. 点击 PERSONAL ACCOUNT 旁边的 Select。
7. 点击 Environment Variables填写 Name 为 `VUE_APP_NETEASE_API_URL`Value 为 `/api`,点击 Add。最后点击底部的 Deploy 就可以部署到
6. 点击 Environment Variables填写 Name 为 `VUE_APP_NETEASE_API_URL`Value 为你刚刚部署的网易云 API 地址,点击 Add。最后点击底部的 Deploy 就可以部署到
Vercel 了。
## ⚙️ 部署到自己的服务器
除了部署到 Vercel你还可以部署到自己的服务器上
1. 部署网易云 API详情参见 [Binaryify/NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi)
2. 克隆本仓库
```sh
git clone --recursive https://github.com/qier222/YesPlayMusic.git
```
3. 安装依赖
```sh
yarn install
```
4. (可选)使用 Nginx 反向代理 API将 API 路径映射为 `/api`,如果 API 和网页不在同一个域名下的话(跨域),会有一些 bug。
5. 复制 `/.env.example` 文件为 `/.env`,修改里面 `VUE_APP_NETEASE_API_URL` 的值为网易云 API 地址。本地开发的话可以填写 API 地址为 `http://localhost:3000`YesPlayMusic 地址为 `http://localhost:8080`。如果你使用了反向代理 API可以填写 API 地址为 `/api`
```
VUE_APP_NETEASE_API_URL=http://localhost:3000
```
6. 编译打包
```sh
yarn run build
```
7. 将 `/dist` 目录下的文件上传到你的 Web 服务器
## ⚙️ 宝塔面板 docker应用商店 部署
1. 安装宝塔面板,前往[宝塔面板官网](https://www.bt.cn/new/download.html) ,选择正式版的脚本下载安装。
2. 安装后登录宝塔面板,在左侧导航栏中点击 Docker首次进入会提示安装Docker服务点击立即安装按提示完成安装
3. 安装完成后在应用商店中找到YesPlayMusic点击安装配置域名、端口等基本信息即可完成安装。
4. 安装后在浏览器输入上一步骤设置的域名即可访问。
## ⚙️ Docker 部署
1. 构建 Docker Image
```sh
docker build -t yesplaymusic .
```
2. 启动 Docker Container
```sh
docker run -d --name YesPlayMusic -p 80:80 yesplaymusic
```
3. Docker Compose 启动
```sh
docker-compose up -d
```
YesPlayMusic 地址为 `http://localhost`
## ⚙️ 部署至 Replit
1. 新建 Repl选择 Bash 模板
2. 在 Replit shell 中运行以下命令
```sh
bash <(curl -s -L https://raw.githubusercontent.com/qier222/YesPlayMusic/main/install-replit.sh)
```
3. 首次运行成功后,只需点击绿色按钮 `Run` 即可再次运行
4. 由于 replit 个人版限制内存为 1G教育版为 3G构建过程中可能会失败请再次运行上述命令或运行以下命令
```sh
cd /home/runner/${REPL_SLUG}/music && yarn install && yarn run build
```
## 👷‍♂️ 打包客户端
如果在 Release 页面没有找到适合你的设备的安装包的话,你可以根据下面的步骤来打包自己的客户端。
@ -182,7 +69,7 @@ cd /home/runner/${REPL_SLUG}/music && yarn install && yarn run build
1. 打包 Electron 需要用到 Node.js 和 Yarn。可前往 [Node.js 官网](https://nodejs.org/zh-cn/) 下载安装包。安装 Node.js
后可在终端里执行 `npm install -g yarn` 来安装 Yarn。
2. 使用 `git clone --recursive https://github.com/qier222/YesPlayMusic.git` 克隆本仓库到本地。
2. 使用 `git clone https://github.com/qier222/YesPlayMusic.git` 克隆本仓库到本地。
3. 使用 `yarn install` 安装项目依赖。
@ -199,13 +86,13 @@ cd /home/runner/${REPL_SLUG}/music && yarn install && yarn run build
## :computer: 配置开发环境
本项目由 [NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi) 提供 API。
本项目由 [NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi) 提供 API,已经包含在本项目的`netease_api`目录
运行本项目
```shell
# 安装依赖
yarn install
yarn
# 创建本地环境变量
cp .env.example .env
@ -220,6 +107,9 @@ yarn electron:serve
本地运行 NeteaseCloudMusicApi或者将 API [部署至 Vercel](#%EF%B8%8F-部署至-vercel)
```shell
# 安装依赖
yarn netease_api:install
# 运行 API (默认 3000 端口)
yarn netease_api:run
```
@ -247,24 +137,26 @@ API 源代码来自 [Binaryify/NeteaseCloudMusicApi](https://github.com/Binaryif
## 🖼️ 截图
![lyrics][lyrics-screenshot]
![library-dark][library-dark-screenshot]
![album][album-screenshot]
![home-2][home-2-screenshot]
![artist][artist-screenshot]
![search][search-screenshot]
![home][home-screenshot]
![explore][explore-screenshot]
[![artist][artist-screenshot]](https://music.qier222.com)
[![album][album-screenshot]](https://music.qier222.com)
[![playlist][playlist-screenshot]](https://music.qier222.com)
[![explore][explore-screenshot]](https://music.qier222.com)
[![search][search-screenshot]](https://music.qier222.com)
[![home][home-screenshot]](https://music.qier222.com)
<!-- MARKDOWN LINKS & IMAGES -->
<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
[album-screenshot]: images/album.png
[artist-screenshot]: images/artist.png
[explore-screenshot]: images/explore.png
[home-screenshot]: images/home.png
[home-2-screenshot]: images/home-2.png
[lyrics-screenshot]: images/lyrics.png
[library-screenshot]: images/library.png
[library-dark-screenshot]: images/library-dark.png
[playlist-screenshot]: images/playlist.png
[search-screenshot]: images/search.png

View file

@ -1,11 +1,7 @@
module.exports = {
presets: [
[
'@vue/cli-plugin-babel/preset',
{
useBuiltIns: 'usage',
shippedProposals: true,
},
],
presets: ["@vue/cli-plugin-babel/preset"],
plugins: [
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-optional-chaining",
],
};

View file

@ -1,132 +0,0 @@
{
"nodes": {
"devenv": {
"locked": {
"dir": "src/modules",
"lastModified": 1730412360,
"owner": "cachix",
"repo": "devenv",
"rev": "45847cb1f14a6d8cfa86ea943703c54a8798ae7e",
"type": "github"
},
"original": {
"dir": "src/modules",
"owner": "cachix",
"repo": "devenv",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1730272153,
"owner": "nixos",
"repo": "nixpkgs",
"rev": "2d2a9ddbe3f2c00747398f3dc9b05f7f2ebb0f53",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1730327045,
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "080166c15633801df010977d9d7474b4a6c549d7",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nodejs16": {
"locked": {
"lastModified": 1700230496,
"owner": "nixos",
"repo": "nixpkgs",
"rev": "a71323f68d4377d12c04a5410e214495ec598d4c",
"type": "github"
},
"original": {
"owner": "nixos",
"repo": "nixpkgs",
"rev": "a71323f68d4377d12c04a5410e214495ec598d4c",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1730302582,
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "af8a16fe5c264f5e9e18bcee2859b40a656876cf",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"devenv": "devenv",
"nixpkgs": "nixpkgs",
"nodejs16": "nodejs16",
"pre-commit-hooks": "pre-commit-hooks"
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,53 +0,0 @@
{ pkgs, lib, config, inputs, ... }:
let
nodejs16 = import inputs.nodejs16 { system = pkgs.stdenv.system; };
in
{
# https://devenv.sh/basics/
env.GREET = "devenv";
# https://devenv.sh/packages/
packages = [ pkgs.git ] ++ lib.optionals pkgs.stdenv.isDarwin (with pkgs.darwin.apple_sdk; [
frameworks.AppKit
]);
# https://devenv.sh/languages/
languages.javascript.enable = true;
languages.javascript.package = nodejs16.pkgs.nodejs_16;
languages.javascript.corepack.enable = true;
# languages.rust.enable = true;
# https://devenv.sh/processes/
# processes.cargo-watch.exec = "cargo-watch";
# https://devenv.sh/services/
# services.postgres.enable = true;
# https://devenv.sh/scripts/
scripts.hello.exec = ''
echo hello from $GREET
'';
enterShell = ''
hello
git --version
'';
# https://devenv.sh/tasks/
# tasks = {
# "myproj:setup".exec = "mytool build";
# "devenv:enterShell".after = [ "myproj:setup" ];
# };
# https://devenv.sh/tests/
enterTest = ''
echo "Running tests"
git --version | grep --color=auto "${pkgs.git.version}"
'';
# https://devenv.sh/pre-commit-hooks/
# pre-commit.hooks.shellcheck.enable = true;
# See full reference at https://devenv.sh/reference/options/
}

View file

@ -1,19 +0,0 @@
# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
inputs:
nixpkgs:
url: github:nixos/nixpkgs/nixpkgs-unstable
nodejs16:
url: github:nixos/nixpkgs/a71323f68d4377d12c04a5410e214495ec598d4c
# https://github.com/cachix/devenv/issues/792#issuecomment-2043166453
impure: true
# If you're using non-OSS software, you can set allowUnfree to true.
# allowUnfree: true
# If you're willing to use a package that's vulnerable
# permittedInsecurePackages:
# - "openssl-1.1.1w"
# If you have more than one devenv you can merge them
#imports:
# - ./backend

View file

@ -1,39 +0,0 @@
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 -
# environment:
# JSON_LOG: true
# LOG_LEVEL: debug
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

View file

@ -1,28 +0,0 @@
server {
gzip on;
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
location @rewrites {
rewrite ^(.*)$ /index.html last;
}
location /api/ {
proxy_buffers 16 32k;
proxy_buffer_size 128k;
proxy_busy_buffers_size 128k;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Host $remote_addr;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:3000/;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 253 KiB

After

Width:  |  Height:  |  Size: 804 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 730 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 KiB

After

Width:  |  Height:  |  Size: 1.4 MiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 389 KiB

After

Width:  |  Height:  |  Size: 1.4 MiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 335 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 339 KiB

BIN
images/playlist.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

After

Width:  |  Height:  |  Size: 1 MiB

Before After
Before After

View file

@ -1,28 +0,0 @@
#!/usr/bin/bash
# 初始化 .replit 和 replit.nix
if [[ $1 == i ]];then
echo -e 'run = ["bash", "main.sh"]\n\nentrypoint = "main.sh"' >.replit
echo -e "{ pkgs }: {\n\t\tdeps = [\n\t\t\tpkgs.nodejs-16_x\n\t\t\tpkgs.yarn\n\t\t\tpkgs.bashInteractive\n\t\t];\n}" > replit.nix
exit
fi
# 安装
if [[ ! -d api ]];then
mkdir api
git clone https://github.com/Binaryify/NeteaseCloudMusicApi ./api && \
cd api && npm install && cd ..
fi
if [[ ! -d music ]];then
mkdir music
git clone https://github.com/qier222/YesPlayMusic ./music && \
cd music && cp .env.example .env && npm install --force && npm run build && cd ..
fi
# 启动
PID=`ps -ef | grep npm | awk '{print $2}' | sed '$d'`
if [[ ! -z ${PID} ]];then echo $PID | xargs kill;fi
nohup bash -c 'cd api && PORT=35216 node app.js' > api.log 2>&1
nohup bash -c 'npx serve music/dist/' > music.log 2>&1

View file

@ -7,8 +7,7 @@
},
"target": "ES6",
"module": "commonjs",
"allowSyntheticDefaultImports": true,
"jsx": "preserve"
"allowSyntheticDefaultImports": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]

34
netease_api/.editorconfig Normal file
View file

@ -0,0 +1,34 @@
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# Matches multiple files with brace expansion notation
# Set default charset
[*.{js,py}]
charset = utf-8
# 4 space indentation
[*.py]
indent_style = space
indent_size = 4
# Tab indentation (no size specified)
[Makefile]
indent_style = tab
# Indentation override for all JS under lib directory
[*.{js,ts}]
indent_style = space
indent_size = 2
# Matches the exact files either package.json or .travis.yml
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2

49
netease_api/.eslintrc.js Normal file
View file

@ -0,0 +1,49 @@
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint',
ecmaVersion: 2018,
sourceType: 'module',
},
plugins: ['html'],
extends: ['plugin:prettier/recommended'],
env: {
browser: true,
node: true,
},
rules: {
indent: ['error', 2, { SwitchCase: 1 }],
'space-infix-ops': ['error', { int32Hint: false }],
'key-spacing': [
2,
{
beforeColon: false,
afterColon: true,
},
],
'no-octal': 2,
'no-redeclare': 2,
'comma-spacing': 2,
'no-new-object': 2,
'arrow-spacing': 2,
quotes: [
2,
'single',
{
avoidEscape: true,
allowTemplateLiterals: true,
},
],
},
overrides: [
{
files: ['**/*.ts'],
parser: '@typescript-eslint/parser',
extends: [
'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
'prettier/@typescript-eslint',
],
},
],
}

5
netease_api/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
.DS_Store
node_modules
*.log
.idea
.vscode

4
netease_api/.npmignore Normal file
View file

@ -0,0 +1,4 @@
static
docs
node_modules
module_example

5
netease_api/.prettierrc Normal file
View file

@ -0,0 +1,5 @@
{
"semi": false,
"trailingComma": "all",
"singleQuote": true
}

4
netease_api/.travis.yml Normal file
View file

@ -0,0 +1,4 @@
language: node_js
node_js:
- 12

747
netease_api/CHANGELOG.MD Normal file
View file

@ -0,0 +1,747 @@
# 更新日志
### 4.0.8 | 2021.2.27
- 加入vercel 配置文件,支持 vercel 部署
### 4.0.7 | 2021.2.27
- 更新红心接口,修复红心接口460错误问题 [#1151](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1151)
- 更新发送验证码接口
- 注册接口添加 countrycode 参数 [#1152](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1152)
- 新增绑定手机接口 [#1152](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1152)
- 更新 song/detail 接口 [#1143](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1143)
- 用户粉丝接口修改分页参数 [#1161](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1161)
### 4.0.6 | 2021.2.20
- 修复 eapi 接口无法正确解密response的问题 [#1138](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1138)
### 4.0.5 | 2021.2.19
- 修复红心接口默认不红心的问题 [#1126](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1126)
### 4.0.4 | 2021.2.18
- 移除云村热评接口(官方下架) [#1111](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1111)
- 更新 app version
### 4.0.3 | 2021.1.28
- 修复云盘接口中文音乐信息乱码的问题 [#1108](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1108)
### 4.0.2 | 2021.1.18
- 修复未绑定手机号对歌单添加或删除歌曲无响应的问题 [#1099](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1099)
### 4.0.1 | 2021.1.09
- 新增歌单详情动态接口 [#1088](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1088)
### 4.0.0 | 2021.1.03
- 新增云盘上传接口,新增二维码登录相关接口和相关demo(http://localhost:3000/qrlogin.html, http://localhost:3000/cloud.html),更新 d.ts
- 升级部分接口加密方法("linuxapi" 都替换到了"api")
- 更新 `login/status` 接口(返回字段和之前不一样)
### 3.47.5 | 2020.12.20
- 更新appver [#1060](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1060)
### 3.47.4 | 2020.12.03
- 修复收藏的专栏接口无法调用的问题 [#1042](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1042)
### 3.47.3 | 2020.11.22
- 新增歌手详情接口 [#1035](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1035)
### 3.47.2 | 2020.11.15
- 新增关注歌手新歌/新MV接口 [#1028](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1028)
### 3.47.1 | 2020.11.14
- 修复使用post请求取消喜欢音乐会失败的问题 [#1024](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1024)
- 新增抱一抱评论和评论抱一抱列表接口 [#1016](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1016)
- 新增收藏的专栏接口[#1026](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1026)
### 3.46.1 | 2020.11.7
- 修复私信音乐接口出现风险提示的问题
### 3.46.0 | 2020.11.7
- 添加私信音乐接口 [#1016](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1016)
- 添加最近联系人接口
- 修复用户动态数量不准确问题 [#1010](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1010)
- 修复 cloudsearch 接口分页问题 [#1015](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1015)
### 3.45.3 | 2020.11.1
- `相似歌手`,`首页-发现-圆形图标入口列表`接口增加匿名token[#877](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/877) [#988](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/988)
- 修复`音乐 url`接口POST方式手动传入cookie报错问题 [#1005](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/1005)
### 3.45.2 | 2020.10.26
- 云贝完成任务接口增加`depositCode`参数
### 3.45.1 | 2020.10.25
- 修复代理配置失效的问题 [#992](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/992)
- 修复新碟上架不返回周数据的问题,修复推荐新音乐接口返回数量问题,并添加limit参数支持 [#981](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/981)
- 添加`云贝`相关接口 [#985](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/985)
- 添加`用户账号信息`接口
- 替换接口文件所有http url 为 https
### 3.44.0 | 2020.10.17
- 更新`电台详情`,`电台节目详情`接口 [#977](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/977)
#### Breaking change
- `电台详情`接口更新后数据结构有变化
### 3.43.0 | 2020.10.16
- 新增`电台订阅者列表`接口 [#971](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/971)
### 3.42.4 | 2020.10.07
- 修复新评论接口分页参数问题
### 3.42.3 | 2020.10.05
- 修复新评论接口分页参数问题
### 3.42.2 | 2020.10.05
- 更新歌单详情接口
### 3.42.1 | 2020.10.04
- 新增`用户绑定信息`,`用户绑定手机`,`新版评论`,`点赞过的视频`,`收藏视频到视频歌单`,`删除视频歌单里的视频`,`最近播放的视频`,`音乐日历`等接口
- 创建歌单接口增加`type`参数,可创建视频歌单
### 3.41.2 | 2020.09.20
- 更新`获取音乐 url`接口,未登录状态返回试听片段 [#897](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/897)
### 3.41.1 | 2020.09.19
- 新增`电台个性推荐接口` [#824](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/824)
### 3.41.0 | 2020.09.19
- 新增`精品歌单标签列表`接口 [#921](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/921)
- 新增`用户等级信息`接口 [#929](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/929)
- 增加新接口的 d.ts 文件,修复登录接口的 d.ts 的 countrycode 为非可选属性的错误
### 3.40.1 | 2020.09.13
- 更新 TypeScript 声明 [#928](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/928)
### 3.40.0 | 2020.09.12
- 新增 TypeScript 声明文件 [#908](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/908)
- 更改随机 UA 相关逻辑[#922](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/922)
### 3.39.0 | 2020.08.23
- 新增`cloudsearch`接口[#893](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/893)
- `mv 地址`接口修改分辨率参数 [#883](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/883)
- 修复新碟上架接口分页问题 [#892](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/892)
### 3.38.0 | 2020.08.09
- 新增`楼层评论`,`歌手全部歌曲`接口 [#864](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/864) [#867](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/867)
- 支持收藏VIP或付费歌曲到歌单 [#860](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/860)
- 支持手动传入`realIP` [#863](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/863)
### 3.37.2 | 2020.08.04
- 修复依赖问题
### 3.37.0 | 2020.08.03
- 新增`更新头像`,`歌单封面上传`接口和相关例子 [#403](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/403) [#857](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/857)
- 加入`axios`依赖
### 3.36.0 | 2020.07.26
- 新增`全部新碟`,`数字专辑-新碟上架`,`数字专辑&数字单曲-榜单`,`数字专辑-语种风格馆`,`数字专辑详情`接口 [#852](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/852)
- 更新`新碟上架`接口,修改传入参数,返回数据结构有变化
### 3.35.0 | 2020.07.18
- 新增`首页-发现`,`首页-发现-圆形图标入口列表`接口 [#851](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/851)
### 3.34.2 | 2020.07.13
- 修复`获取用户播放记录`接口参数错误问题 [#849](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/849)
- 增加`国家编码列表`接口 [#841](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/841)
### 3.34.1 | 2020.07.06
- 登录接口增加 `md5_password` 参数 [#839](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/839)
### 3.34.0 | 2020.06.25
- 排行榜接口废弃idx参数,只支持id参数,修复返回数据异常问题 [#830](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/830)
- 新增`获取历史日推可用日期列表`,`获取历史日推详细数据` 接口
### 3.33.2 | 2020.06.23
- 更新每日推荐接口 [#826](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/826)
### 3.33.1 | 2020.06.15
- 修复直接调用时传入 cookie 不生效的问题 [#822](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/822)
### 3.33.0 | 2020.06.10
- 歌手榜支持地区参数 [#818](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/818)
- 新增视频分类列表,推荐视频,获取全部视频列表接口 [#816](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/816)
- 内置 apicache,修复不能在 NodeJS v13 版本使用的问题 [#817](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/817)
### 3.32.3 | 2020.06.07
- 修复 Nodejs 下 cookie 使用格式问题 [#812](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/812)
### 3.32.2 | 2020.06.05
- 新增独家放送列表接口 [#808](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/808)
### 3.32.1 | 2020.06.03
- 新增歌曲排序接口
### 3.32.0 | 2020.06.03
- 更新排行榜接口,支持传入榜单id
- 新增榜单顺序调整接口 [#806](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/806)
- 完善错误提示信息
### 3.31.1 | 2020.05.19
- 修复`cookie`没返回的问题 [#778](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/778)
### 3.31.0 | 2020.05.18
- 支持 `Node.js` 调用,参考`module_example` 文件夹下的 `test.js`
### 3.30.0 | 2020.05.17
- 登录接口返回内容增加`cookie`字段,支持手动传入cookie
### 3.29.1 | 2020.05.13
- 调整通知接口分页参数 [#761](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/761)
### 3.29.0 | 2020.05.11
- 支持批量删除歌单 [#760](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/760)
### 3.28.0 | 2020.05.05
- 新增获取 mv 点赞转发评论数数据接口
- 新增获取视频点赞转发评论数数据接口
### 3.27.0 | 2020.04.20
- 新增购买专辑接口 by [TimonPeng](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/740)
### 3.26.0 | 2020.04.08
#### Breaking change
- 更新歌手分类列表接口参数,因`cat`参数失效,调整为`type``area`参数
### 3.25.4 | 2020.03.18
- 更新歌词,歌手分类列表接口
- 更新文档
### 3.25.3 | 2019.11.08
- 升级依赖,去除多余依赖
- 优化 `test.html`
### 3.25.2 | 2019.11.07
- 修复邮箱登录状态码错误,增加相关提示 [#633](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/633)
### 3.25.0 | 2019.11.06
- 新增 `云村热评` 接口[#626](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/626)
- 新增 `歌手热门50首歌曲` 接口
- 新增`电台24小时节目榜`,`电台24小时主播榜`, `电台最热主播榜`,`电台主播新人榜`,`电台付费精品榜` 接口 [#606](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/606)
- 调整 `歌手分类列表 ` 接口参数 [#624](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/624)
### 3.24.2 | 2019.10.28
- 修改默认绑定 HOST [#620](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/620)
### 3.24.1 | 2019.10.25
- 修改默认绑定 HOST [#615](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/615)
### 3.24.0 | 2019.10.22
- 新增`类别热门电台` 接口 [#607](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/607)
### 3.23.0 | 2019.10.16
- 修复电台 banner 接口无数据问题[#601](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/601)
- 更新排行榜 [#602](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/602)
- 新增`电台排行榜`,`新晋电台榜`,`热门电台榜`接口 [#604](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/604)
### 3.22.4 | 2019.09.26
- 修复私信历史记录分页参数问题,更新文档 [#599](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/599)
### 3.22.3 | 2019.09.24
- 手机号码检测: 添加国家码作为参数,方便检测国外手机号码 [#598](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/598)
### 3.22.2 | 2019.09.18
- 排行榜参数更新,更新文档[#592](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/592)
### 3.22.1 | 2019.09.12
- 支持回复评论[#589](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/589)
### 3.22.0 | 2019.08.25
- 支持 CORS 预检 [#564](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/564) [#578](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/578)
### 3.21.1 | 2019.08.21
- 修复推荐歌单和网易出品mv参数错误,更新文档 [#571](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/571) [#572](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/572)
### 3.21.0 | 2019.08.20
- 新增`歌单删除接口`[#570](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/570)
### 3.20.0 | 2019.08.06
- 新增`更新歌单描述`,`更新歌单名`,`更新歌单标签`,`默认搜索关键词` 接口,更新文档[#547](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/547)
### 3.19.0 | 2019.07.24
- 新增`检测手机号码是否已注册``初始化昵称`接口[#540](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/540)
### 3.18.6 | 2019.07.15
- 修复注册异常的问题 [#532](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/532)
### 3.18.5 | 2019.07.14
- 修复部分歌曲无法获得播放链接的问题 [#531](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/531)
### 3.18.3 | 2019.07.04
- 修复全部 mv`/mv/all` 接口分页参数错误的问题 [#524](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/524)
### 3.18.2 | 2019.07.03
- 修复听歌打卡接口 `/scrobble` 失效问题
### 3.18.1 | 2019.06.30
- 评论接口增加 `before` 参数以获取超过5000条评论数据 [#521](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/521)
- 修复 `/msg/comments` 传入参数和文档描述不一致问题
### 3.18.0 | 2019.06.29
- 新增 `更换绑定手机接口`
#### Breaking change
1. 调整注册接口由 `/captch/register` 修改为 `/register/cellphone`
2. 调整发送短信接口由 `/captch/sent` 修改为 `/captcha/sent`
3. 调整短信验证接口由 `/captch/verify` 修改为 `/captcha/verify`
### 3.17.0 | 2019.06.29
- 新增 `专辑动态信息` `热搜列表(详细)` 接口,更新文档
### 3.16.0 | 2019.06.27
- 新增 `收藏/取消收藏专辑` 接口
- 调整歌曲评论接口使用客户端版本接口
### 3.15.0 | 2019.06.16
- 新增`获取视频标签列表`,`网易出品`,`全部mv`接口, `最新 mv``mv 排行` 接口加入地区参数,更新文档
### 3.14.0 | 2019.06.10
- 获取用户粉丝列表接口修改请求参数,更新文档
### 3.13.1 | 2019.06.09
- 修复获取用户粉丝列表接口只能获取1000个的问题
### 3.13.0 | 2019.05.19
- 新增eapi算法 (via:[#491](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/491))
- 新增batch批量请求接口 (via:[#491](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/491))
- 用户动态增加分页参数
### 3.12.0 | 2019.05.10
- 增加`私信内容、我的数字专辑`接口
### 3.11.0 | 2019.05.09
- 增加`通知-私信、通知-评论、通知-@我、通知-通知、设置、云盘数据详情`接口
### 3.10.2 | 2019.05.09
- 增加`分享歌曲、歌单、mv、电台、电台节目到动态`接口
### 3.10.1 | 2019.05.08
- 增加转发动态接口
- 增加删除动态接口
### 3.9.0 | 2019.05.03
- 新增 云盘歌曲删除, 热门话题, 电台 - 推荐类型, 电台 - 非热门类型, 电台 - 今日优选, 心动模式/智能播放等接口
- 更新文档:banner接口 增加 `type` 参数; 获取动态消息接口增加 `pagesize``lasttime` 参数; 电台 - 付费精选接口修改默认`limit`为 30
### 3.8.1 | 2019.04.24
- 修复歌词接口出错问题
### 3.8.0 | 2019.04.14
- 增加注册,发送验证码,校验验证码接口 via:[https://github.com/Binaryify/NeteaseCloudMusicApi/pull/460](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/460) @[KongValley](https://github.com/KongValley)
### 3.7.1 | 2019.04.09
- 修复登录460问题
### 3.7.0 | 2019.03.20
- 修复喜欢音乐接口参数判断问题
- 增加歌单收藏者列表接口
### 3.6.0 | 2019.03.15
- 调整动态评论获取接口 url使之和其他评论获取接口更统一
### 3.5.0 | 2019.03.14
- 增加获取动态评论接口
- 支持给动态点赞
- 支持给动态评论点赞
- 支持给动态发送/删除评论
### 3.4.0 | 2019.01.29
- 增加已收藏专辑列表接口
### 3.3.0 | 2019.01.27
- 增加视频标签下的视频获取接口
- 增加 pac 代理支持
### 3.2.0 | 2019.01.19
- 增加获取首页新碟上架数据以及更新听歌排行
- 更新搜索建议接口
### 3.1.0 | 2019.01.06
- 修复评论接口返回 460 Cheating 的问题
- 新增`已收藏MV`接口,更新文档
### 3.0.9 | 2018.12.15
- 修复关注异常的问题 #399
### 3.0.8 | 2018.12.12
- 更新文档 #386 #394
- 优化电台节目接口
### 3.0.7 | 2018.11.21
- 修复歌单详情列表,排行榜,所有榜单失效的问题,更新文档 #380 #381
### 3.0.4 | 2018.11.15
- 修复 `/song/url` 接口无法返回多个音乐数据的问题
### 3.0.3 | 2018.11.09
- 修复取消喜欢歌曲失败问题 [#360](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/360)
- 补充已喜欢音乐列表接口说明文档 [#370](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/370)
- 默认关闭 debug 模式 [#365](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/365)
- 更新 Dockerfile 文件 [#367](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/367)
### 3.0.1 | 2018.10.21
- 合并 PR([#351](https://github.com/Binaryify/NeteaseCloudMusicApi/pull/351))
- 文档增加 `/top/song` 接口
- `/banner` 换成 linux api返回结构有所变动
- `/check/music` 已知 bug 修复
### 3.0.0 | 2018.10.14
#### 整体
- 完善文档,增加之前没写进文档的接口说明
- 重写 createRequest 返回 Promise 对象
- 模块化路由
- 模块化, 剥离 res,req, 方便导出调用
- 增加 cookie-parser
##### 参数修改
- `/song/detail` 增加多 id 支持
- `/toplist/detail` 移除参数
- `/resource/like` 增加参数 `type`
- `/top/playlist/highquality` 增加分页参数 `before`
##### 统一参数
- `/artist/sub``artist/unsub` 合并, 用`query.t`
- `/follow``query.type` 换成 `query.t`
- `/comment``query.action` 换成 `query.t`
##### URL 重命名
- `/video` 改为 `video/url`
- `/mv` 改为 `mv/detail`
- `/music/url` 改为 `/song/url`
##### 转发逻辑修改
- `/toplist/artist` 换成 weapi
- `/mv/url` 去除了 pipe
##### BUG 修复
- `/playlist/create`, `/playlist/update` 被判欺骗,增加 cookie
##### 路由增删
- 删除 `/recommend/dislike`
- 增加 `/video/sub` (收藏视频), `/mv/sub` (收藏 MV)
- 增加 `/video/detail` (视频详情)
- 增加 `/related/allvideo` (相关视频)
### 2.20.5 | 2018.09.29
修复非法参数 403 #335, 修复代理错误 #334
### 2.20.4 | 2018.09.27
修复点赞失效的问题
### 2.20.3 | 2018.09.26
- 增加退出登录接口
- 修正 /check/music 的检查逻辑
- 优化 Cookies 设置
- 重构单元测试
[by @nondanee](https://github.com/nondanee)
- 增加 301 需要登录提示信息
- 更新文档
### 2.20.2 | 2018.09.22
增加热门评论和视频评论接口,更新文档
### 2.20.1 | 2018.09.17
优化版本检查功能
### 2.20.0 | 2018.09.06
新增版本检查功能
### 2.19.0 | 2018.08.29
新增获取视频数据接口,新增发送/删除评论接口,修复登录状态接口问题,完善文档 #301,感谢 @izhenyuls
### 2.17.0 | 2018.08.28
新增登录状态查询接口 #302 ,完善文档,完善路由注册 #297
### 2.16.0 | 2018.08.09
- Fixed #288,#289,#290
解决歌曲 URL 请求被判 Cheating,修复私信接收异常 #291
### 2.15.0 | 2018.07.30
新增相关歌单推荐和付费精选接口,增加歌手列表接口按首字母索引查找参数
### 2.14.0 | 2018.07.03
修复无法使用邮箱问题
### 2.13.0 | 2018.06.05
增加自动注册路由的功能,简化路由注册逻辑
### 2.12.0 | 2018.05.27
更新文档,优化歌单详情接口
### 2.11.1 | 2018.05.24
更新文档,优化`/dj/program`接口
### 2.11.0 | 2018.05.21
增加收藏歌手列表&订阅电台列表
### 2.10.0 | 2018.05.17
歌单操作调整为批量操作
### 2.9.9 | 2018.05.16
Bug 修复
### 2.9.8 | 2018.05.10
新增歌手分类列表,收藏/取消收藏歌手接口,新增更新用户信息,更新歌单接口
### 2.9.6 | 2018.05.08
新增发送私信相关接口,新增新建歌单,收藏/取消收藏歌单接口
### 2.9.4 | 2018.05.04
新增热搜接口,更新 banner 接口
### 2.9.2 | 2018.02.28
修复登录失败会崩溃的问题
### 2.9.1 | 2018.01.26
docker 构建文件的一些增强以及增加访问日志和调试输出
### 2.8.9 | 2018.01.24
修复歌单详情数据不完整的问题,更新依赖
### 2.8.8 | 2018.01.22
修复排行榜数据不完整的问题 , 优化部分代码 , 更新文档部分描述
### 2.8.6 | 2018.01.16
修复歌单详情接口数据不完整的问题
### 2.8.5 | 2018.01.16
修复评论点赞失败的问题
### 2.8.4 | 2018.01.15
优化 cookie 设置
### 2.8.3 | 2018.01.12
优化部分功能和文档
### 2.8.2 | 2018.01.05
增加 Dockerfile支持以 Docker 容器模式运行
### 2.8.1 | 2018.01.04
添加了 proxy 功能
### 2.8.0 | 2018.01.04
用 'request' 重写了请求函数
### 2.7.9 | 2017.12.11
更新排行榜接口 , 新增云音乐 ACG 音乐榜 , 云音乐嘻哈榜
### 2.7.7 | 2017.11.27
更新 / 修复排行榜接口 , 更新 / 修复推荐歌单接口
### 2.7.7 | 2017.11.27
更新 / 修复排行榜接口 , 更新 / 修复推荐歌单接口
### 2.7.2 | 2017.9.7
修复搜索接口 offset 参数失效问题
### 2.7.0 | 2017.8.21
优化刷新登录代码
### 2.6.5 | 2017.7.16
优化 CORS 设置
### 2.6.4 | 2017.7.16
添加缓存机制和随机 UA 机制 感谢[@u3u](https://github.com/u3u)
[issue:77](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/77) 优化请求
代码 感谢 [@huhuime](https://github.com/huhuime)
[issue:83](https://github.com/Binaryify/NeteaseCloudMusicApi/issues/83)
### 2.6.2 | 2017.7.16
修复垃圾桶接口
### 2.6.1 | 2017.7.16
修复红心接口
### 2.6.0 | 2017.6.25
修复签到接口
### 2.5.9 | 2017.6.14
增加启动说明页
### 2.5.8 | 2017.6.1
修复若干细节问题
### 2.5.7 | 2017.5.22
修复若干问题
### 2.5.6 | 2017.5.14
增加动态消息接口
### 2.5.5 | 2017.5.10
修复 mv 排行榜接口崩溃问题
### 2.5.4 | 2017.5.5
新增点赞接口 , 更新文档
### 2.5.3 | 2017.5.2
修复歌手单曲数据空白问题和文档获取歌手单曲 url 描述问题 , 更新文档
### 2.5.0 | 2017.4.29
增加 mv/ 专辑 / 歌单评论接口 , 增加云盘相关接口 , 增加获取用户动态 / 信息接口 ,
增加关注 / 粉丝列表接口 , 增加收藏歌单接口 , 增加相似 mv/ 歌曲 / 用户接口 , 增加
banner 接口 , 增加刷新登录接口 , 增加电台相关接口 , 补充评论接口 , 更新文档
### 2.4.6 | 2017.4.21
增加播放 mv 接口 , 更新文档
### 2.4.5 | 2017.4.20
增加歌手专辑 , 歌手单曲等接口 , 修复 /album 接口描述错误 , 更新文档
### 2.4.0 | 2017.4.20
增加歌单(网友精选碟 ), 新碟上架 , 热门歌手等接口 , 更新文档
### 2.3.4 | 2017.4.20
增加歌曲详情接口 , 更新文档
### 2.3.0 | 2017.4.15
增加排行榜接口 , 更新文档
### 2.2.0 |2017.4.14
增加私人 FM, 喜欢歌曲 , 垃圾桶 , 每日签到等接口 , 更新文档
### 2.1.3 | 2017.4.6
改善文档
### 2.1.0 | 2017.4.6
增加获取评论接口以及对应单元测试 , 增加更新日志
### 2.0.0 | 2017.4.1
版本升级到 2.0. 增加使用文档 , 完成项目重构 , 增加更完善的单元测试 , 升级 api 到
v2+, 支持登录并获取用户信息和创建的歌单 , 可通过获取音乐 url 接口获取用户歌单里
的的音乐 , 获取每日推荐歌单和每日推荐音乐

13
netease_api/Dockerfile Normal file
View file

@ -0,0 +1,13 @@
FROM node:lts-alpine
WORKDIR /app
COPY . /app
RUN rm -f package-lock.json \
; rm -rf .idea \
; rm -rf node_modules \
; npm config set registry "https://registry.npm.taobao.org/" \
&& npm install
EXPOSE 3000
CMD ["node", "app.js"]

21
netease_api/LICENSE Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-2016 Binaryify
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

338
netease_api/README.MD Normal file
View file

@ -0,0 +1,338 @@
# 网易云音乐 API
网易云音乐 Node.js API service
<p>
<a href="https://www.npmjs.com/package/NeteaseCloudMusicApi"><img src="https://img.shields.io/npm/v/NeteaseCloudMusicApi.svg" alt="Version"></a>
<a href="https://www.npmjs.com/package/NeteaseCloudMusicApi"><img src="https://img.shields.io/npm/l/NeteaseCloudMusicApi.svg" alt="License"></a>
<a href="https://www.npmjs.com/package/NeteaseCloudMusicApi"><img src="https://img.shields.io/david/dev/binaryify/NeteaseCloudMusicApi.svg" alt="devDependencies" ></a>
<a href="https://www.npmjs.com/package/NeteaseCloudMusicApi"><img src="https://img.shields.io/david/binaryify/NeteaseCloudMusicApi.svg" alt="devDependencies" ></a>
<a href="https://codeclimate.com/github/Binaryify/NeteaseCloudMusicApi"><img src="https://codeclimate.com/github/Binaryify/NeteaseCloudMusicApi/badges/gpa.svg" /></a>
</p>
## 灵感来自
[disoul/electron-cloud-music](https://github.com/disoul/electron-cloud-music)
[darknessomi/musicbox](https://github.com/darknessomi/musicbox)
[sqaiyan/netmusic-node](https://github.com/sqaiyan/netmusic-node)
[greats3an/pyncm](https://github.com/greats3an/pyncm)
## 环境要求
需要 NodeJS 8.12+ 环境
## 安装
```shell
$ git clone git@github.com:Binaryify/NeteaseCloudMusicApi.git
$ npm install
```
或者
```shell
$ git clone https://github.com/Binaryify/NeteaseCloudMusicApi.git
$ npm install
```
## 运行
```shell
$ node app.js
```
服务器启动默认端口为 3000,若不想使用 3000 端口,可使用以下命令: Mac/Linux
```shell
$ PORT=4000 node app.js
```
windows 下使用 git-bash 或者 cmder 等终端执行以下命令:
```shell
$ set PORT=4000 && node app.js
```
## Vercel 部署
v4.0.8 加入了 Vercel 配置文件,可以直接在 Vercel 下部署了,不需要自己的服务器
### 操作方法
1. fork 此项目
2. 在 Vercel 官网点击 `New Project`
3. 点击 `Import Git Repository` 并选择你 fork 的此项目并点击`import`
4. 点击 `PERSONAL ACCOUNT``select`
5. 直接点`Continue`
6. `PROJECT NAME`自己填,`FRAMEWORK PRESET``Other` 然后直接点 `Deploy` 接着等部署完成即可
## 可以在Node.js调用
v3.31.0后支持Node.js调用,导入的方法为`module`内的文件名,返回内容包含`status``body`,`status`为状态码,`body`为请求返回内容,参考`module_example` 文件夹下的 `test.js`
```js
const { login_cellphone, user_cloud } = require('NeteaseCloudMusicApi')
async function main() {
try {
const result = await login_cellphone({
phone: '手机号',
password: '密码'
})
console.log(result)
const result2 = await user_cloud({
cookie: result.body.cookie // 凭证
})
console.log(result2.body)
} catch (error) {
console.log(error)
}
}
main()
```
## 支持 TypeScript
```ts
// test.ts
import { banner } from 'NeteaseCloudMusicApi'
banner({ type:0 }).then(res=>{
console.log(res)
})
```
## 使用文档
[文档地址](https://binaryify.github.io/NeteaseCloudMusicApi)
[文档地址2](https://neteasecloudmusicapi.vercel.app)
![文档](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/docs.png)
## 功能特性
1. 登录
2. 刷新登录
3. 发送验证码
4. 校验验证码
5. 注册(修改密码)
6. 获取用户信息 , 歌单收藏mv, dj 数量
7. 获取用户歌单
8. 获取用户电台
9. 获取用户关注列表
10. 获取用户粉丝列表
11. 获取用户动态
12. 获取用户播放记录
13. 获取精品歌单
14. 获取歌单详情
15. 搜索
16. 搜索建议
17. 获取歌词
18. 歌曲评论
19. 收藏单曲到歌单
20. 专辑评论
21. 歌单评论
22. mv 评论
23. 电台节目评论
24. banner
25. 获取歌曲详情
26. 获取专辑内容
27. 获取歌手单曲
28. 获取歌手 mv
29. 获取歌手专辑
30. 获取歌手描述
31. 获取相似歌手
32. 获取相似歌单
33. 相似 mv
34. 获取相似音乐
35. 获取最近 5 个听了这首歌的用户
36. 获取每日推荐歌单
37. 获取每日推荐歌曲
38. 私人 FM
39. 签到
40. 喜欢音乐
41. 垃圾桶
42. 歌单 ( 网友精选碟 )
43. 新碟上架
44. 热门歌手
45. 最新 mv
46. 推荐 mv
47. 推荐歌单
48. 推荐新音乐
49. 推荐电台
50. 推荐节目
51. 独家放送
52. mv 排行
53. 获取 mv 数据
54. 播放 mv/视频
55. 排行榜
56. 歌手榜
57. 云盘
58. 电台 - 推荐
59. 电台 - 分类
60. 电台 - 分类推荐
61. 电台 - 订阅
62. 电台 - 详情
63. 电台 - 节目
64. 给评论点赞
65. 获取动态
66. 热搜列表(简略)
67. 发送私信
68. 发送私信歌单
69. 新建歌单
70. 收藏/取消收藏歌单
71. 歌单分类
72. 收藏的歌手列表
73. 订阅的电台列表
74. 相关歌单推荐
75. 付费精选接口
76. 音乐是否可用检查接口
77. 登录状态
78. 获取视频播放地址
79. 发送/删除评论
80. 热门评论
81. 视频评论
82. 退出登录
83. 所有榜单
84. 所有榜单内容摘要
85. 收藏视频
86. 收藏 MV
87. 视频详情
88. 相关视频
89. 关注用户
90. 新歌速递
91. 喜欢音乐列表(无序)
92. 收藏的 MV 列表
93. 获取最新专辑
94. 听歌打卡
95. 获取视频标签/分类下的视频
96. 已收藏专辑列表
97. 获取动态评论
98. 歌单收藏者列表
99. 云盘歌曲删除
100. 热门话题
101. 电台 - 推荐类型
102. 电台 - 非热门类型
103. 电台 - 今日优选
104. 心动模式/智能播放
105. 转发动态
106. 删除动态
107. 分享歌曲、歌单、mv、电台、电台节目到动态
108. 通知-私信
109. 通知-评论
110. 通知-@我
111. 通知-通知
112. 设置
113. 云盘数据详情
114. 私信内容
115. 我的数字专辑
116. batch批量请求接口
117. 获取视频标签列表
118. 全部mv
119. 网易出品mv
120. 收藏/取消收藏专辑
121. 专辑动态信息
122. 热搜列表(详细)
123. 更换绑定手机
124. 检测手机号码是否已注册
125. 初始化昵称
126. 更新歌单描述
127. 更新歌单名
128. 更新歌单标签
129. 默认搜索关键词
130. 删除歌单
131. 电台banner
132. 用户电台
133. 热门电台
134. 电台 - 节目详情
135. 电台 - 节目榜
136. 电台 - 新晋电台榜/热门电台榜
137. 类别热门电台
138. 云村热评
139. 电台24小时节目榜
140. 电台24小时主播榜
141. 电台最热主播榜
142. 电台主播新人榜
143. 电台付费精品榜
144. 歌手热门50首歌曲
145. 购买数字专辑
146. 获取 mv 点赞转发评论数数据
147. 获取视频点赞转发评论数数据
148. 调整歌单顺序
149. 调整歌曲顺序
150. 独家放送列表
151. 获取推荐视频
152. 获取视频分类列表
153. 获取全部视频列表接口
154. 获取历史日推可用日期列表
155. 获取历史日推详细数据
156. 国家编码列表
157. 首页-发现
158. 首页-发现-圆形图标入口列表
159. 数字专辑-全部新碟
160. 数字专辑-热门新碟
161. 数字专辑&数字单曲-榜单
162. 数字专辑-语种风格馆
163. 数字专辑详情
164. 更新头像
165. 歌单封面上传
166. 楼层评论
167. 歌手全部歌曲
168. 精品歌单标签列表
169. 用户等级信息
170. 电台个性推荐
171. 用户绑定信息
172. 用户绑定手机
173. 新版评论
174. 点赞过的视频
175. 收藏视频到视频歌单
176. 删除视频歌单里的视频
177. 最近播放的视频
178. 音乐日历
179. 电台订阅者列表
180. 云贝签到信息
181. 云贝签到
182. 云贝所有任务
183. 云贝todo任务
184. 云贝今日签到信息
185. 云贝完成任务
186. 云贝收入
187. 云贝支出
188. 云贝账户信息
189. 账号信息
190. 最近联系人
191. 私信音乐
192. 抱一抱评论
193. 评论抱一抱列表
194. 收藏的专栏
195. 关注歌手新歌
196. 关注歌手新MV
197. 歌手详情
198. 云盘上传
199. 二维码登录
200. 话题详情
201. 话题详情热门动态
202. 歌单详情动态
203. 绑定手机
## 更新日志
[changelog](https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/CHANGELOG.MD)
## 单元测试
```shell
$ npm test
```
![单元测试](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/screenshot1.png)
![单元测试](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/screenshot2.png)
## 贡献者
![](https://opencollective.com/NeteaseCloudMusicApi/contributors.svg?width=890)
## License
[The MIT License (MIT)](https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/LICENSE)

117
netease_api/app.js Normal file
View file

@ -0,0 +1,117 @@
const fs = require('fs')
const path = require('path')
const express = require('express')
const bodyParser = require('body-parser')
const request = require('./util/request')
const packageJSON = require('./package.json')
const exec = require('child_process').exec
const cache = require('./util/apicache').middleware
const { cookieToJson } = require('./util/index')
const fileUpload = require('express-fileupload')
// version check
exec('npm info NeteaseCloudMusicApi version', (err, stdout, stderr) => {
if (!err) {
let version = stdout.trim()
if (packageJSON.version < version) {
console.log(
`最新版本: ${version}, 当前版本: ${packageJSON.version}, 请及时更新`,
)
}
}
})
const app = express()
// CORS & Preflight request
app.use((req, res, next) => {
if (req.path !== '/' && !req.path.includes('.')) {
res.set({
'Access-Control-Allow-Credentials': true,
'Access-Control-Allow-Origin': req.headers.origin || '*',
'Access-Control-Allow-Headers': 'X-Requested-With,Content-Type',
'Access-Control-Allow-Methods': 'PUT,POST,GET,DELETE,OPTIONS',
'Content-Type': 'application/json; charset=utf-8',
})
}
req.method === 'OPTIONS' ? res.status(204).end() : next()
})
// cookie parser
app.use((req, res, next) => {
req.cookies = {}
;(req.headers.cookie || '').split(/\s*;\s*/).forEach((pair) => {
let crack = pair.indexOf('=')
if (crack < 1 || crack == pair.length - 1) return
req.cookies[
decodeURIComponent(pair.slice(0, crack)).trim()
] = decodeURIComponent(pair.slice(crack + 1)).trim()
})
next()
})
// body parser
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
app.use(fileUpload())
// static
app.use(express.static(path.join(__dirname, 'public')))
// cache
app.use(cache('2 minutes', (req, res) => res.statusCode === 200))
// router
const special = {
'daily_signin.js': '/daily_signin',
'fm_trash.js': '/fm_trash',
'personal_fm.js': '/personal_fm',
}
fs.readdirSync(path.join(__dirname, 'module'))
.reverse()
.forEach((file) => {
if (!file.endsWith('.js')) return
let route =
file in special
? special[file]
: '/' + file.replace(/\.js$/i, '').replace(/_/g, '/')
let question = require(path.join(__dirname, 'module', file))
app.use(route, (req, res) => {
if (typeof req.query.cookie === 'string') {
req.query.cookie = cookieToJson(req.query.cookie)
}
let query = Object.assign(
{},
{ cookie: req.cookies },
req.query,
req.body,
req.files,
)
question(query, request)
.then((answer) => {
console.log('[OK]', decodeURIComponent(req.originalUrl))
res.append('Set-Cookie', answer.cookie)
res.status(answer.status).send(answer.body)
})
.catch((answer) => {
console.log('[ERR]', decodeURIComponent(req.originalUrl), {
status: answer.status,
body: answer.body,
})
if (answer.body.code == '301') answer.body.msg = '需要登录'
res.append('Set-Cookie', answer.cookie)
res.status(answer.status).send(answer.body)
})
})
})
const port = process.env.PORT || 3000
const host = process.env.HOST || ''
app.server = app.listen(port, host, () => {
console.log(`server running @ http://${host ? host : 'localhost'}:${port}`)
})
module.exports = app

15
netease_api/app.test.js Normal file
View file

@ -0,0 +1,15 @@
const fs = require('fs')
const path = require('path')
let app
before(() => {
app = require('./app.js')
global.host = 'http://localhost:' + app.server.address().port
})
after((done) => {
app.server.close(done)
})
fs.readdirSync(path.join(__dirname, 'test')).forEach((file) => {
require(path.join(__dirname, 'test', file))
})

View file

3253
netease_api/docs/README.md Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,13 @@
# 网易云音乐 API
> 网易云音乐 NodeJS 版 API
- 全部接口已升级到最新
- 具备登录接口,多达200多个接口
- 更完善的文档
[GitHub](https://github.com/Binaryify/NeteaseCloudMusicApi)
[Get Started](#neteasecloudmusicapi)
![color](#ffffff)

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
netease_api/docs/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="KEYWords" contect="网易云音乐,网易云音乐 api,网易云音乐 nodejs,网易云音乐 node.js">
<meta name="description" content="网易云音乐 NodeJS 版 API">
<title>网易云音乐 NodeJS 版 API</title>
<link rel="icon" href="favicon.ico">
<meta name="description" content="Description">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta name="referrer" content="never">
<link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<script>
(adsbygoogle = window.adsbygoogle || []).push({
google_ad_client: "ca-pub-5159844745975514",
enable_page_level_ads: true
});
</script>
</head>
<body>
<div id="app"></div>
</body>
<script>
window.$docsify = {
name: '网易云音乐 API',
repo: 'https://github.com/Binaryify/NeteaseCloudMusicApi',
coverpage: true
}
</script>
<script src="https://unpkg.com/docsify@4.11.3/lib/docsify.min.js"></script>
<script>
if (typeof navigator.serviceWorker !== 'undefined') {
navigator.serviceWorker.register('sw.js')
}
</script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-139996012-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-139996012-1');
</script>
</html>

90
netease_api/docs/sw.js Normal file
View file

@ -0,0 +1,90 @@
/* ===========================================================
* docsify sw.js
* ===========================================================
* Copyright 2016 @huxpro
* Licensed under Apache 2.0
* Register service worker.
* ========================================================== */
const RUNTIME = 'docsify'
const HOSTNAME_WHITELIST = [
self.location.hostname,
'fonts.gstatic.com',
'fonts.googleapis.com',
'unpkg.com',
]
// The Util Function to hack URLs of intercepted requests
const getFixedUrl = (req) => {
var now = Date.now()
var url = new URL(req.url)
// 1. fixed http URL
// Just keep syncing with location.protocol
// fetch(httpURL) belongs to active mixed content.
// And fetch(httpRequest) is not supported yet.
url.protocol = self.location.protocol
// 2. add query for caching-busting.
// Github Pages served with Cache-Control: max-age=600
// max-age on mutable content is error-prone, with SW life of bugs can even extend.
// Until cache mode of Fetch API landed, we have to workaround cache-busting with query string.
// Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190
if (url.hostname === self.location.hostname) {
url.search += (url.search ? '&' : '?') + 'cache-bust=' + now
}
return url.href
}
/**
* @Lifecycle Activate
* New one activated when old isnt being used.
*
* waitUntil(): activating ====> activated
*/
self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim())
})
/**
* @Functional Fetch
* All network requests are being intercepted here.
*
* void respondWith(Promise<Response> r)
*/
self.addEventListener('fetch', (event) => {
// Skip some of cross-origin requests, like those for Google Analytics.
if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) {
// Stale-while-revalidate
// similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale
// Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1
const cached = caches.match(event.request)
const fixedUrl = getFixedUrl(event.request)
const fetched = fetch(fixedUrl, { cache: 'no-store' })
const fetchedCopy = fetched.then((resp) => resp.clone())
// Call respondWith() with whatever we get first.
// If the fetch fails (e.g disconnected), wait for the cache.
// If theres nothing in cache, wait for the fetch.
// If neither yields a response, return offline pages.
event.respondWith(
Promise.race([fetched.catch((_) => cached), cached])
.then((resp) => resp || fetched)
.catch((_) => {
/* eat any errors */
}),
)
// Update the cache with the version we fetched (only for ok status)
event.waitUntil(
Promise.all([fetchedCopy, caches.open(RUNTIME)])
.then(
([response, cache]) =>
response.ok && cache.put(event.request, response),
)
.catch((_) => {
/* eat any errors */
}),
)
}
})

1429
netease_api/docs/v2.md Normal file

File diff suppressed because it is too large Load diff

1
netease_api/index.js Normal file
View file

@ -0,0 +1 @@
require('./app.js')

1407
netease_api/interface.d.ts vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,29 @@
## 环境
- 系统/平台: <你的系统和平台>
- nodejs 版本: <你的 NodeJS 版本号>
- API版本:<运行的云音乐 API 的版本号 对应 package.json 里面的 version>
## 出现问题
<出现的问题>
## 重现步骤
<重现步骤>
## 期待效果
<现在的效果期待的效果>
>先看文档有没有相关说明,调用前须知必看
>先在 issues 搜一下是否有相似问题,没有再发,否则直接关闭
>不处理别人搭建的线上服务的问题,此项目不提供任何线上服务,请自行搭建
>重现步骤尽量详细,不能含糊不清,包含请求地址和对应参数以及操作过程描述,不是每个人都喜欢猜别人遇到了什么问题和找参数一个个试,也比较浪费时间
>如果不是提建议,提 issues 如果不照着模版来将不会优先处理或直接关闭
>460 cheating 的问题把 `utils/request.js` 里面的 `headers['X-Real-IP']` 的注释取消掉就好

26
netease_api/main.js Normal file
View file

@ -0,0 +1,26 @@
const fs = require('fs')
const path = require('path')
const request = require('./util/request')
const { cookieToJson } = require('./util/index')
let obj = {}
fs.readdirSync(path.join(__dirname, 'module'))
.reverse()
.forEach((file) => {
if (!file.endsWith('.js')) return
let fileModule = require(path.join(__dirname, 'module', file))
obj[file.split('.').shift()] = function (data) {
if (typeof data.cookie === 'string') {
data.cookie = cookieToJson(data.cookie)
}
return fileModule(
{
...data,
cookie: data.cookie ? data.cookie : {},
},
request,
)
}
})
module.exports = obj

View file

@ -0,0 +1,19 @@
// 初始化名字
module.exports = (query, request) => {
const data = {
nickname: query.nickname,
}
return request(
'POST',
`https://music.163.com/eapi/activate/initProfile`,
data,
{
crypto: 'eapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
url: '/api/activate/initProfile',
},
)
}

View file

@ -0,0 +1,15 @@
// 专辑内容
module.exports = (query, request) => {
return request(
'POST',
`https://music.163.com/weapi/v1/album/${query.id}`,
{},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,17 @@
// 数字专辑详情
module.exports = (query, request) => {
const data = {
id: query.id,
}
return request(
'POST',
`https://music.163.com/weapi/vipmall/albumproduct/detail`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,17 @@
// 专辑动态信息
module.exports = (query, request) => {
const data = {
id: query.id,
}
return request(
'POST',
`https://music.163.com/api/album/detail/dynamic`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,21 @@
// 数字专辑-新碟上架
module.exports = (query, request) => {
const data = {
limit: query.limit || 30,
offset: query.offset || 0,
total: true,
area: query.area || 'ALL', //ALL:全部,ZH:华语,EA:欧美,KR:韩国,JP:日本
type: query.type,
}
return request(
'POST',
`https://music.163.com/weapi/vipmall/albumproduct/list`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,20 @@
// 数字专辑-语种风格馆
module.exports = (query, request) => {
const data = {
limit: query.limit || 10,
offset: query.offset || 0,
total: true,
area: query.area || 'Z_H', //Z_H:华语,E_A:欧美,KR:韩国,JP:日本
}
return request(
'POST',
`https://music.163.com/weapi/vipmall/appalbum/album/style`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,15 @@
// 全部新碟
module.exports = (query, request) => {
const data = {
limit: query.limit || 30,
offset: query.offset || 0,
total: true,
area: query.area || 'ALL', //ALL:全部,ZH:华语,EA:欧美,KR:韩国,JP:日本
}
return request('POST', `https://music.163.com/weapi/album/new`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

View file

@ -0,0 +1,15 @@
// 最新专辑
module.exports = (query, request) => {
return request(
'POST',
`https://music.163.com/api/discovery/newAlbum`,
{},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,24 @@
// 数字专辑&数字单曲-榜单
module.exports = (query, request) => {
let data = {
albumType: query.albumType || 0, //0为数字专辑,1为数字单曲
}
const type = query.type || 'daily' // daily,week,year,total
if (type === 'year') {
data = {
...data,
year: query.year,
}
}
return request(
'POST',
`https://music.163.com/api/feealbum/songsaleboard/${type}/type`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,14 @@
// 收藏/取消收藏专辑
module.exports = (query, request) => {
query.t = query.t == 1 ? 'sub' : 'unsub'
const data = {
id: query.id,
}
return request('POST', `https://music.163.com/api/album/${query.t}`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

View file

@ -0,0 +1,15 @@
// 已收藏专辑列表
module.exports = (query, request) => {
const data = {
limit: query.limit || 25,
offset: query.offset || 0,
total: true,
}
return request('POST', `https://music.163.com/weapi/album/sublist`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

View file

@ -0,0 +1,20 @@
// 歌手专辑列表
module.exports = (query, request) => {
const data = {
limit: query.limit || 30,
offset: query.offset || 0,
total: true,
}
return request(
'POST',
`https://music.163.com/weapi/artist/albums/${query.id}`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,18 @@
// 歌手介绍
module.exports = (query, request) => {
const data = {
id: query.id,
}
return request(
'POST',
`https://music.163.com/weapi/artist/introduction`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,15 @@
module.exports = (query, request) => {
return request(
'POST',
`https://music.163.com/api/artist/head/info/get`,
{
id: query.id,
},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,37 @@
// 歌手分类
/*
type 取值
1:男歌手
2:女歌手
3:乐队
area 取值
-1:全部
7华语
96欧美
8:日本
16韩国
0:其他
initial 取值 a-z/A-Z
*/
module.exports = (query, request) => {
const data = {
initial: isNaN(query.initial)
? (query.initial || '').toUpperCase().charCodeAt() || undefined
: query.initial,
offset: query.offset || 0,
limit: query.limit || 30,
total: true,
type: query.type || '1',
area: query.area,
}
return request('POST', `https://music.163.com/api/v1/artist/list`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

View file

@ -0,0 +1,16 @@
// 歌手相关MV
module.exports = (query, request) => {
const data = {
artistId: query.id,
limit: query.limit,
offset: query.offset,
total: true,
}
return request('POST', `https://music.163.com/weapi/artist/mvs`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

View file

@ -0,0 +1,19 @@
module.exports = (query, request) => {
query.cookie.os = 'ios'
query.cookie.appver = '8.1.20'
const data = {
limit: query.limit || 20,
startTimestamp: query.before || Date.now(),
}
return request(
'POST',
`https://music.163.com/api/sub/artist/new/works/mv/list`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,19 @@
module.exports = (query, request) => {
query.cookie.os = 'ios'
query.cookie.appver = '8.1.20'
const data = {
limit: query.limit || 20,
startTimestamp: query.before || Date.now(),
}
return request(
'POST',
`https://music.163.com/api/sub/artist/new/works/song/list`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,17 @@
module.exports = (query, request) => {
query.cookie.os = 'pc'
const data = {
id: query.id,
private_cloud: 'true',
work_type: 1,
order: query.order || 'hot', //hot,time
offset: query.offset || 0,
limit: query.limit || 100,
}
return request('POST', `https://music.163.com/api/v1/artist/songs`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

View file

@ -0,0 +1,20 @@
// 收藏与取消收藏歌手
module.exports = (query, request) => {
query.t = query.t == 1 ? 'sub' : 'unsub'
const data = {
artistId: query.id,
artistIds: '[' + query.id + ']',
}
return request(
'POST',
`https://music.163.com/weapi/artist/${query.t}`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,15 @@
// 关注歌手列表
module.exports = (query, request) => {
const data = {
limit: query.limit || 25,
offset: query.offset || 0,
total: true,
}
return request('POST', `https://music.163.com/weapi/artist/sublist`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

View file

@ -0,0 +1,12 @@
// 歌手热门 50 首歌曲
module.exports = (query, request) => {
const data = {
id: query.id,
}
return request('POST', `https://music.163.com/api/artist/top/song`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

View file

@ -0,0 +1,15 @@
// 歌手单曲
module.exports = (query, request) => {
return request(
'POST',
`https://music.163.com/weapi/v1/artist/${query.id}`,
{},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,19 @@
const realData =
'eJx10mtIU2EcBvDtnCwNMfO2klUSmSQ5ZugKW/v/0TIjJVdhDStbXpqXrhY5Kwhtrcwiut9VSqMUMxX6IFqsD92sD1YgWGHRBcowKrpnPa/v+drg4flt572ds2PQ6XQut7MwJ940w2TOyS0pzF+/BV/MJrNO+3TVLOHUzKx5iw3/H5uZ7yxegct3tTl7Cr6QEa0gZ/dZOFsvfe5YHe1D+yFZxpncqEj/cCdwoirdVxHNnZrX3xygU5g7Eh6I9uOx8Ch4y9FQjlKkDz1pYrFXIJLUOovFGcYivqJgXqaXDqu7Rzc0XzmZxG81B/fF8wRVusn2jN5rDnwca8tFhyAJP4L4qiI9vX8cWzEmVKzT/46qxNpIdZOZz2HNcHhSkZ3D4AjYFpfGFkX6+dB+FvcSBe/SWbkLPVnEOJ1DFelXxVVci/Wj4TsBLhrQ/LGoaU4HxsTA28L76Cc8Dfau/U6F6FgkyBDDJar0g8tesmOvOHioWeXXmme6l3MLbIIre6wciU5E2t/k8WVxHfHvuUWXsH4SPCv1NW1Cz0aivgYO34vw1AEvi3MlIw0xHl6JNVPEGW41UJsqPaXYYTuEnotMdHwYfv7CFR/i+aXmrY5wrlSkEwr+0EJ0GvLmdw4/RS9Amj93UAbGZMIF40ezE3PtcG/yBWrT3L6oh66hFyMXK4xsUKT7aufzapxnFTwiNc3Wis5Bdm+OYCvmOuHj/ZeoQPOI00PUrUjXpG+kMFU61tFFDvQaZOn5DH4mzoLw4Hsaj14rzu/K4jF66fSWTnJinW3wBvcveqjZN3iFjKp0qKuF1mi21keST3NtTcbwu1eG3Dussr9eemljLIco0tVH7HwA493wOr+FlIjfy+GvkR4uwfjt4v/6G8K3NX8K38lt6B1ISa+Bv2O8Fy69foZOovci2S4Lr1aku4P9OEWVTt9wgMQ7exgJ8JXyI0W694WFyuBjcH75XyrEXsfhg+ZSvqZIf/Lct8Wp0md2tJN4PifEfjcm8gu02Ptbj459eum8eg8bFWlLXTb/A+uo9bM='
module.exports = (query, request) => {
query.cookie.os = 'pc'
const data = {
algorithmCode: 'shazam_v2',
times: 1,
sessionId: 'C999431ACDC84EDBB984763654E6F8D7',
duration: 3.3066249999999995,
from: 'recognize-song',
rawdata: realData,
}
return request('POST', `https://music.163.com/api/music/audio/match`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

View file

@ -0,0 +1,27 @@
const uploadPlugin = require('../plugins/upload')
module.exports = async (query, request) => {
const uploadInfo = await uploadPlugin(query, request)
const res = await request(
'POST',
`https://music.163.com/weapi/user/avatar/upload/v1`,
{
imgid: uploadInfo.imgId,
},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
return {
status: 200,
body: {
code: 200,
data: {
...uploadInfo,
...res.body,
},
},
}
}

View file

@ -0,0 +1,17 @@
// 首页轮播图
module.exports = (query, request) => {
const type =
{
0: 'pc',
1: 'android',
2: 'iphone',
3: 'ipad',
}[query.type || 0] || 'pc'
return request(
'POST',
`https://music.163.com/api/v2/banner/get`,
{ clientType: type },
{ crypto: 'api', proxy: query.proxy, realIP: query.realIP },
)
}

View file

@ -0,0 +1,19 @@
// 批量请求接口
module.exports = (query, request) => {
const data = {
e_r: true,
}
Object.keys(query).forEach((i) => {
if (/^\/api\//.test(i)) {
data[i] = query[i]
}
})
return request('POST', `https://music.163.com/eapi/batch`, data, {
crypto: 'eapi',
proxy: query.proxy,
url: '/api/batch',
cookie: query.cookie,
realIP: query.realIP,
})
}

View file

@ -0,0 +1,12 @@
module.exports = (query, request) => {
const data = {
startTime: query.startTime || Date.now(),
endTime: query.endTime || Date.now(),
}
return request('POST', `https://music.163.com/api/mcalendar/detail`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

View file

@ -0,0 +1,14 @@
// 发送验证码
module.exports = (query, request) => {
const data = {
ctcode: query.ctcode || '86',
cellphone: query.phone,
}
return request('POST', `https://music.163.com/api/sms/captcha/sent`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

View file

@ -0,0 +1,20 @@
// 校验验证码
module.exports = (query, request) => {
const data = {
ctcode: query.ctcode || '86',
cellphone: query.phone,
captcha: query.captcha,
}
return request(
'POST',
`https://music.163.com/weapi/sms/captcha/verify`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,20 @@
// 检测手机号码是否已注册
module.exports = (query, request) => {
const data = {
cellphone: query.phone,
countrycode: query.countrycode,
}
return request(
'POST',
`https://music.163.com/eapi/cellphone/existence/check`,
data,
{
crypto: 'eapi',
cookie: query.cookie,
proxy: query.proxy,
url: '/api/cellphone/existence/check',
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,34 @@
// 歌曲可用性
module.exports = (query, request) => {
const data = {
ids: '[' + parseInt(query.id) + ']',
br: parseInt(query.br || 999000),
}
return request(
'POST',
`https://music.163.com/weapi/song/enhance/player/url`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
).then((response) => {
let playable = false
if (response.body.code == 200) {
if (response.body.data[0].code == 200) {
playable = true
}
}
if (playable) {
response.body = { success: true, message: 'ok' }
return response
} else {
response.status = 404
response.body = { success: false, message: '亲爱的,暂无版权' }
return Promise.reject(response)
}
})
}

147
netease_api/module/cloud.js Normal file
View file

@ -0,0 +1,147 @@
const mm = require('music-metadata')
const uploadPlugin = require('../plugins/songUpload')
const md5 = require('md5')
module.exports = async (query, request) => {
query.cookie.os = 'pc'
query.cookie.appver = '2.7.1.198277'
const bitrate = 999000
if (!query.songFile) {
return Promise.reject({
status: 500,
body: {
msg: '请上传音乐文件',
code: 500,
},
})
}
if (!query.songFile.md5) {
// 命令行上传没有md5和size信息,需要填充
query.songFile.md5 = md5(query.songFile.data)
query.songFile.size = query.songFile.data.byteLength
}
const res = await request(
'POST',
`https://interface.music.163.com/api/cloud/upload/check`,
{
bitrate: String(bitrate),
ext: '',
length: query.songFile.size,
md5: query.songFile.md5,
songId: '0',
version: 1,
},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
let artist = ''
let album = ''
let songName = ''
try {
const metadata = await mm.parseBuffer(query.songFile.data, 'audio/mpeg')
const info = metadata.common
if (info.title) {
songName = info.title
}
if (info.album) {
album = info.album
}
if (info.artist) {
artist = info.artist
}
// if (metadata.native.ID3v1) {
// metadata.native.ID3v1.forEach((item) => {
// // console.log(item.id, item.value)
// if (item.id === 'title') {
// songName = item.value
// }
// if (item.id === 'artist') {
// artist = item.value
// }
// if (item.id === 'album') {
// album = item.value
// }
// })
// // console.log({
// // songName,
// // album,
// // songName,
// // })
// }
// console.log({
// songName,
// album,
// songName,
// })
} catch (error) {
console.log(error)
}
const tokenRes = await request(
'POST',
`https://music.163.com/weapi/nos/token/alloc`,
{
bucket: '',
ext: 'mp3',
filename: query.songFile.name.replace('.mp3', ''),
local: false,
nos_product: 3,
type: 'audio',
md5: query.songFile.md5,
},
{ crypto: 'weapi', cookie: query.cookie, proxy: query.proxy },
)
if (res.body.needUpload) {
const uploadInfo = await uploadPlugin(query, request)
// console.log('uploadInfo', uploadInfo.body.result.resourceId)
}
// console.log(tokenRes.body.result)
const res2 = await request(
'POST',
`https://music.163.com/api/upload/cloud/info/v2`,
{
md5: query.songFile.md5,
songid: res.body.songId,
filename: query.songFile.name,
song: songName || query.songFile.name.replace('.mp3', ''),
album: album || '未知专辑',
artist: artist || '未知艺术家',
bitrate: String(bitrate),
resourceId: tokenRes.body.result.resourceId,
},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
// console.log({ res2, privateCloud: res2.body.privateCloud })
// console.log(res.body.songId, 'songid')
const res3 = await request(
'POST',
`https://interface.music.163.com/api/cloud/pub/v2`,
{
songid: res2.body.songId,
},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
// console.log({ res3 })
return {
status: 200,
body: {
...res.body,
...res3.body,
// ...uploadInfo,
},
cookie: res.cookie,
}
}

View file

@ -0,0 +1,17 @@
// 搜索
module.exports = (query, request) => {
const data = {
s: query.keywords,
type: query.type || 1, // 1: 单曲, 10: 专辑, 100: 歌手, 1000: 歌单, 1002: 用户, 1004: MV, 1006: 歌词, 1009: 电台, 1014: 视频
limit: query.limit || 30,
offset: query.offset || 0,
total: true,
}
return request('POST', `https://music.163.com/api/cloudsearch/pc`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

View file

@ -0,0 +1,36 @@
const { resourceTypeMap } = require('../util/config.json')
// 发送与删除评论
module.exports = (query, request) => {
query.cookie.os = 'pc'
query.t = {
1: 'add',
0: 'delete',
2: 'reply',
}[query.t]
query.type = resourceTypeMap[query.type]
const data = {
threadId: query.type + query.id,
}
if (query.type == 'A_EV_2_') {
data.threadId = query.threadId
}
if (query.t == 'add') data.content = query.content
else if (query.t == 'delete') data.commentId = query.commentId
else if (query.t == 'reply') {
data.commentId = query.commentId
data.content = query.content
}
return request(
'POST',
`https://music.163.com/weapi/resource/comments/${query.t}`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,22 @@
// 专辑评论
module.exports = (query, request) => {
query.cookie.os = 'pc'
const data = {
rid: query.id,
limit: query.limit || 20,
offset: query.offset || 0,
beforeTime: query.before || 0,
}
return request(
'POST',
`https://music.163.com/weapi/v1/resource/comments/R_AL_3_${query.id}`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,22 @@
// 电台评论
module.exports = (query, request) => {
query.cookie.os = 'pc'
const data = {
rid: query.id,
limit: query.limit || 20,
offset: query.offset || 0,
beforeTime: query.before || 0,
}
return request(
'POST',
`https://music.163.com/weapi/v1/resource/comments/A_DJ_1_${query.id}`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,20 @@
// 获取动态评论
module.exports = (query, request) => {
const data = {
limit: query.limit || 20,
offset: query.offset || 0,
beforeTime: query.before || 0,
}
return request(
'POST',
`https://music.163.com/weapi/v1/resource/comments/${query.threadId}`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,21 @@
const { resourceTypeMap } = require('../util/config.json')
module.exports = (query, request) => {
query.type = resourceTypeMap[query.type]
const data = {
parentCommentId: query.parentCommentId,
threadId: query.type + query.id,
time: query.time || -1,
limit: query.limit || 20,
}
return request(
'POST',
`https://music.163.com/api/resource/comment/floor/get`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,24 @@
const { resourceTypeMap } = require('../util/config.json')
// 热门评论
module.exports = (query, request) => {
query.cookie.os = 'pc'
query.type = resourceTypeMap[query.type]
const data = {
rid: query.id,
limit: query.limit || 20,
offset: query.offset || 0,
beforeTime: query.before || 0,
}
return request(
'POST',
`https://music.163.com/weapi/v1/resource/hotcomments/${query.type}${query.id}`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,27 @@
const { resourceTypeMap } = require('../util/config.json')
module.exports = (query, request) => {
query.cookie.os = 'ios'
query.cookie.appver = '8.1.20'
query.type = resourceTypeMap[query.type || 0]
const threadId = query.type + query.sid
const data = {
targetUserId: query.uid,
commentId: query.cid,
cursor: query.cursor || '-1',
threadId: threadId,
pageNo: query.page || 1,
idCursor: query.idCursor || -1,
pageSize: query.pageSize || 100,
}
return request(
'POST',
`https://music.163.com/api/v2/resource/comments/hug/list`,
data,
{
crypto: 'api',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,26 @@
const { resourceTypeMap } = require('../util/config.json')
// 点赞与取消点赞评论
module.exports = (query, request) => {
query.cookie.os = 'pc'
query.t = query.t == 1 ? 'like' : 'unlike'
query.type = resourceTypeMap[query.type]
const data = {
threadId: query.type + query.id,
commentId: query.cid,
}
if (query.type == 'A_EV_2_') {
data.threadId = query.threadId
}
return request(
'POST',
`https://music.163.com/weapi/v1/comment/${query.t}`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,22 @@
// 歌曲评论
module.exports = (query, request) => {
query.cookie.os = 'pc'
const data = {
rid: query.id,
limit: query.limit || 20,
offset: query.offset || 0,
beforeTime: query.before || 0,
}
return request(
'POST',
`https://music.163.com/api/v1/resource/comments/R_SO_4_${query.id}`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,22 @@
// MV评论
module.exports = (query, request) => {
query.cookie.os = 'pc'
const data = {
rid: query.id,
limit: query.limit || 20,
offset: query.offset || 0,
beforeTime: query.before || 0,
}
return request(
'POST',
`https://music.163.com/weapi/v1/resource/comments/R_MV_5_${query.id}`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

View file

@ -0,0 +1,31 @@
const { resourceTypeMap } = require('../util/config.json')
// 评论
module.exports = (query, request) => {
query.cookie.os = 'pc'
query.type = resourceTypeMap[query.type]
const threadId = query.type + query.id
const pageSize = query.pageSize || 20
const pageNo = query.pageNo || 1
const data = {
threadId: threadId,
pageNo,
showInner: query.showInner || true,
pageSize,
cursor:
+query.sortType === 3 ? query.cursor || '0' : (pageNo - 1) * pageSize,
sortType: query.sortType || 1, //1:按推荐排序,2:按热度排序,3:按时间排序
}
return request(
'POST',
`https://music.163.com/api/v2/resource/comments`,
data,
{
crypto: 'eapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
url: '/api/v2/resource/comments',
},
)
}

Some files were not shown because too many files have changed in this diff Show more