main
林明友 2 years ago
parent 24fdbdeec6
commit b3e53a6cec

@ -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

@ -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',
],
},
],
}

7
.gitignore vendored

@ -0,0 +1,7 @@
.DS_Store
node_modules
*.log
.idea
.vscode
.history
examples/moddef.json

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

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

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

File diff suppressed because it is too large Load Diff

@ -0,0 +1,11 @@
FROM node:lts-alpine
WORKDIR /app
COPY . /app
RUN npm config set registry "https://registry.npmmirror.com/" \
&& npm install -g npm husky \
&& npm install --production
EXPOSE 3000
CMD ["node", "app.js"]

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-2022 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.

@ -1,2 +1,393 @@
# musicApi
# 网易云音乐 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
$ cd NeteaseCloudMusicApi
$ npm install
```
或者
```shell
$ git clone https://github.com/Binaryify/NeteaseCloudMusicApi.git
$ cd NeteaseCloudMusicApi
$ 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. 绑定手机
204. 一起听状态
205. 用户历史评论
206. 云盘歌曲信息匹配纠正
207. 云贝推歌
208. 云贝推歌历史记录
209. 已购单曲
210. 获取mlog播放地址
211. 将mlog id转为视频id
212. vip成长值
213. vip成长值获取记录
214. vip任务
215. 领取vip成长值
216. 歌手粉丝
217. 数字专辑详情
218. 数字专辑销量
219. 音乐人数据概况
220. 音乐人播放趋势
221. 音乐人任务
222. 账号云豆数
223. 领取云豆
224. 获取 VIP 信息
225. 音乐人签到
226. 发送文本动态
227. 获取客户端歌曲下载 url
228. 获取歌单所有歌曲
229. 乐签信息
230. 最近播放-歌曲
231. 最近播放-视频
232. 最近播放-声音
233. 最近播放-歌单
234. 最近播放-专辑
235. 最近播放-播客
236. 签到进度
237. 重复昵称检测
238. 歌手粉丝数量
239. 音乐人任务(新)
240. 内部版本接口
241. 歌单更新播放量
## 更新日志
[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)
## SDK
| 语言 | 作者 | 地址 | 类型 |
| :--: | :-----------------------------------------: | :----------------------------------------------------------: | :----: |
| Java | [JackuXL](https://github.com/JackuXL) | [https://github.com/JackuXL/NeteaseCloudMusicApi-SDK](https://github.com/JackuXL/NeteaseCloudMusicApi-SDK) | 第三方 |
| Java | [1015770492](https://github.com/1015770492) | https://github.com/1015770492/yumbo-music-utils | 第三方 |
## 贡献者
![](https://opencollective.com/NeteaseCloudMusicApi/contributors.svg?width=890)
## License
[The MIT License (MIT)](https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/LICENSE)

@ -0,0 +1,10 @@
#!/usr/bin/env node
const generateConfig = require('./generateConfig')
async function start() {
// 如果需要手动修改anonymous_token需要注释generateConfig调用
await generateConfig()
require('./server').serveNcmApi({
checkVersion: true,
})
}
start()

@ -0,0 +1,2 @@
const generateConfig = require('./generateConfig')
generateConfig()

File diff suppressed because it is too large Load Diff

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@ -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>

@ -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 */
}),
)
}
})

File diff suppressed because it is too large Load Diff

@ -0,0 +1,22 @@
const fsPromises = require('fs/promises')
const path = require('path')
const server = require('../server')
const exportFile = path.join(__dirname, 'moddef.json')
async function main() {
const def = await server.getModulesDefinitions(
path.join(__dirname, '..', 'module'),
{
'daily_signin.js': '/daily_signin',
'fm_trash.js': '/fm_trash',
'personal_fm.js': '/personal_fm',
},
false,
)
fsPromises.writeFile(exportFile, JSON.stringify(def, null, 4))
console.log(`👍 Get your own definition at: ${exportFile}`)
}
main()

@ -0,0 +1,24 @@
const fs = require('fs')
const { register_anonimous } = require('./main')
const { cookieToJson } = require('./util/index')
const config = require('./util/config.json')
const path = require('path')
async function generateConfig() {
try {
const res = await register_anonimous()
const cookie = res.body.cookie
if (cookie) {
const cookieObj = cookieToJson(cookie)
let newConfig = { ...config }
newConfig.anonymous_token = cookieObj.MUSIC_A
fs.writeFileSync(
path.resolve(__dirname, 'util/config.json'),
JSON.stringify(newConfig, null, 2),
'utf-8',
)
}
} catch (error) {
console.log(error)
}
}
module.exports = generateConfig

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

1625
interface.d.ts vendored

File diff suppressed because it is too large Load Diff

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

@ -0,0 +1,34 @@
const fs = require('fs')
const path = require('path')
const { cookieToJson } = require('./util')
const request = require('./util/request')
/** @type {Record<string, any>} */
let obj = {}
fs.readdirSync(path.join(__dirname, 'module'))
.reverse()
.forEach((file) => {
if (!file.endsWith('.js')) return
let fileModule = require(path.join(__dirname, 'module', file))
let fn = file.split('.').shift() || ''
obj[fn] = function (data = {}) {
if (typeof data.cookie === 'string') {
data.cookie = cookieToJson(data.cookie)
}
return fileModule(
{
...data,
cookie: data.cookie ? data.cookie : {},
},
request,
)
}
})
/**
* @type {Record<string, any> & import("./server")}
*/
module.exports = {
...require('./server'),
...obj,
}

@ -0,0 +1,18 @@
const assert = require('assert')
const main = require('./main')
describe('methods in server.js', () => {
it('has serveNcmApi', () => {
assert.strictEqual(typeof main.serveNcmApi, 'function')
})
it('has getModulesDefinitions', () => {
assert.strictEqual(typeof main.getModulesDefinitions, 'function')
})
})
describe('methods in module', () => {
it('has activate_init_profile', () => {
assert.strictEqual(typeof main.activate_init_profile, 'function')
})
})

@ -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',
},
)
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -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,
})
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -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,
})
}

@ -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,
})
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -0,0 +1,15 @@
// 歌手粉丝
module.exports = (query, request) => {
const data = {
id: query.id,
limit: query.limit || 20,
offset: query.offset || 0,
}
return request('POST', `https://music.163.com/weapi/artist/fans/get`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

@ -0,0 +1,18 @@
// 歌手粉丝数量
module.exports = (query, request) => {
const data = {
id: query.id,
}
return request(
'POST',
`https://music.163.com/weapi/artist/follow/count/get`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -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,
})
}

@ -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,
})
}

@ -0,0 +1,19 @@
module.exports = (query, request) => {
query.cookie.os = 'ios'
query.cookie.appver = '8.7.01'
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,
},
)
}

@ -0,0 +1,19 @@
module.exports = (query, request) => {
query.cookie.os = 'ios'
query.cookie.appver = '8.7.01'
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,
},
)
}

@ -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,
})
}

@ -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,
},
)
}

@ -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,
})
}

@ -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,
})
}

@ -0,0 +1,24 @@
// 歌手相关视频
module.exports = (query, request) => {
const data = {
artistId: query.id,
page: JSON.stringify({
size: query.size || 10,
cursor: query.cursor || 0,
}),
tab: 0,
order: query.order || 0,
}
return request(
'POST',
`https://music.163.com/weapi/mlog/artist/video`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -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,
},
)
}

@ -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,
})
}

@ -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,
},
},
}
}

@ -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 },
)
}

@ -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,
})
}

@ -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,
})
}

@ -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,
})
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -0,0 +1,35 @@
// 歌曲可用性
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 response
// return Promise.reject(response)
}
})
}

@ -0,0 +1,159 @@
const mm = require('music-metadata')
const uploadPlugin = require('../plugins/songUpload')
const md5 = require('md5')
module.exports = async (query, request) => {
let ext = 'mp3'
if (query.songFile.name.indexOf('flac') > -1) {
ext = 'flac'
}
const filename = query.songFile.name
.replace('.' + ext, '')
.replace(/\s/g, '')
.replace(/\./g, '_')
query.cookie.os = 'pc'
query.cookie.appver = '2.9.7'
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,
query.songFile.mimetype,
)
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: ext,
filename: filename,
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 || filename,
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,
}
}

@ -0,0 +1,20 @@
module.exports = (query, request) => {
query.cookie.os = 'ios'
query.cookie.appver = '8.7.01'
const data = {
userId: query.uid,
songId: query.sid,
adjustSongId: query.asid,
}
return request(
'POST',
`https://music.163.com/api/cloud/user/song/match`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -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,
})
}

@ -0,0 +1,36 @@
const { resourceTypeMap } = require('../util/config.json')
// 发送与删除评论
module.exports = (query, request) => {
query.cookie.os = 'android'
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,
},
)
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -0,0 +1,27 @@
const { resourceTypeMap } = require('../util/config.json')
module.exports = (query, request) => {
query.cookie.os = 'ios'
query.cookie.appver = '8.7.01'
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,
},
)
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -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,
},
)
}

@ -0,0 +1,48 @@
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
let sortType = Number(query.sortType) || 99
if (sortType === 1) {
sortType = 99
}
let cursor = ''
switch (sortType) {
case 99:
cursor = (pageNo - 1) * pageSize
break
case 2:
cursor = 'normalHot#' + (pageNo - 1) * pageSize
break
case 3:
cursor = query.cursor || '0'
break
default:
break
}
const data = {
threadId: threadId,
pageNo,
showInner: query.showInner || true,
pageSize,
cursor: cursor,
sortType: sortType, //99:按推荐排序,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',
},
)
}

@ -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_PL_0_${query.id}`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -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_VI_62_${query.id}`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -0,0 +1,16 @@
// 国家编码列表
module.exports = (query, request) => {
const data = {}
return request(
'POST',
`https://interface3.music.163.com/eapi/lbs/countries/v1`,
data,
{
crypto: 'eapi',
cookie: query.cookie,
proxy: query.proxy,
url: '/api/lbs/countries/v1',
realIP: query.realIP,
},
)
}

@ -0,0 +1,20 @@
// 签到
/*
0为安卓端签到 3点经验, 1为网页签到,2点经验
签到成功 {'android': {'point': 3, 'code': 200}, 'web': {'point': 2, 'code': 200}}
重复签到 {'android': {'code': -2, 'msg': '重复签到'}, 'web': {'code': -2, 'msg': '重复签到'}}
未登录 {'android': {'code': 301}, 'web': {'code': 301}}
*/
module.exports = (query, request) => {
const data = {
type: query.type || 0,
}
return request('POST', `https://music.163.com/weapi/point/dailyTask`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

@ -0,0 +1,18 @@
// 数字专辑详情
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,
},
)
}

@ -0,0 +1,27 @@
// 购买数字专辑
module.exports = (query, request) => {
const data = {
business: 'Album',
paymentMethod: query.payment,
digitalResources: JSON.stringify([
{
business: 'Album',
resourceID: query.id,
quantity: query.quantity,
},
]),
from: 'web',
}
return request(
'POST',
`https://music.163.com/api/ordering/web/digital`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -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/api/digitalAlbum/purchased`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -0,0 +1,18 @@
// 数字专辑销量
module.exports = (query, request) => {
const data = {
albumIds: query.ids,
}
return request(
'POST',
`https://music.163.com/weapi/vipmall/albumproduct/album/query/sales`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -0,0 +1,17 @@
// 电台banner
module.exports = (query, request) => {
const data = {}
query.cookie.os = 'pc'
return request(
'POST',
`https://music.163.com/weapi/djradio/banner/get`,
{},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -0,0 +1,15 @@
// 电台非热门类型
module.exports = (query, request) => {
return request(
'POST',
`https://music.163.com/weapi/djradio/category/excludehot`,
{},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -0,0 +1,15 @@
// 电台推荐类型
module.exports = (query, request) => {
return request(
'POST',
`https://music.163.com/weapi/djradio/home/category/recommend`,
{},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -0,0 +1,15 @@
// 电台分类列表
module.exports = (query, request) => {
return request(
'POST',
`https://music.163.com/weapi/djradio/category/get`,
{},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -0,0 +1,13 @@
// 电台详情
module.exports = (query, request) => {
const data = {
id: query.rid,
}
return request('POST', `https://music.163.com/api/djradio/v2/get`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

@ -0,0 +1,14 @@
// 热门电台
module.exports = (query, request) => {
const data = {
limit: query.limit || 30,
offset: query.offset || 0,
}
return request('POST', `https://music.163.com/weapi/djradio/hot/v1`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

@ -0,0 +1,19 @@
// 付费电台
module.exports = (query, request) => {
const data = {
limit: query.limit || 30,
offset: query.offset || 0,
}
return request(
'POST',
`https://music.163.com/weapi/djradio/home/paygift/list?_nmclfl=1`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -0,0 +1,17 @@
// 电台个性推荐
module.exports = (query, request) => {
return request(
'POST',
`https://music.163.com/api/djradio/personalize/rcmd`,
{
limit: query.limit || 6,
},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -0,0 +1,21 @@
// 电台节目列表
const { toBoolean } = require('../util')
module.exports = (query, request) => {
const data = {
radioId: query.rid,
limit: query.limit || 30,
offset: query.offset || 0,
asc: toBoolean(query.asc),
}
return request(
'POST',
`https://music.163.com/weapi/dj/program/byradio`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -0,0 +1,13 @@
// 电台节目详情
module.exports = (query, request) => {
const data = {
id: query.id,
}
return request('POST', `https://music.163.com/api/dj/program/detail`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

@ -0,0 +1,14 @@
// 电台节目榜
module.exports = (query, request) => {
const data = {
limit: query.limit || 100,
offset: query.offset || 0,
}
return request('POST', `https://music.163.com/api/program/toplist/v1`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

@ -0,0 +1,18 @@
// 电台24小时节目榜
module.exports = (query, request) => {
const data = {
limit: query.limit || 100,
// 不支持 offset
}
return request(
'POST',
`https://music.163.com/api/djprogram/toplist/hours`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -0,0 +1,15 @@
// 类别热门电台
module.exports = (query, request) => {
const data = {
cateId: query.cateId,
limit: query.limit || 30,
offset: query.offset || 0,
}
return request('POST', `https://music.163.com/api/djradio/hot`, data, {
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
})
}

@ -0,0 +1,15 @@
// 精选电台
module.exports = (query, request) => {
return request(
'POST',
`https://music.163.com/weapi/djradio/recommend/v1`,
{},
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -0,0 +1,41 @@
// 精选电台分类
/*
有声书 10001
知识技能 453050
商业财经 453051
人文历史 11
外语世界 13
亲子宝贝 14
创作|翻唱 2001
音乐故事 2
3D|电子 10002
相声曲艺 8
情感调频 3
美文读物 6
脱口秀 5
广播剧 7
二次元 3001
明星做主播 1
娱乐|影视 4
科技科学 453052
校园|教育 4001
旅途|城市 12
*/
module.exports = (query, request) => {
const data = {
cateId: query.type,
}
return request(
'POST',
`https://music.163.com/weapi/djradio/recommend`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

@ -0,0 +1,19 @@
// 订阅与取消电台
module.exports = (query, request) => {
query.t = query.t == 1 ? 'sub' : 'unsub'
const data = {
id: query.rid,
}
return request(
'POST',
`https://music.163.com/weapi/djradio/${query.t}`,
data,
{
crypto: 'weapi',
cookie: query.cookie,
proxy: query.proxy,
realIP: query.realIP,
},
)
}

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

Loading…
Cancel
Save