Merge branch 'main' into 'main'
Some checks failed
Update Docker Hub Description / dockerHubDescription (push) Has been skipped
Node.js CI / Test (14.x) (push) Successful in 10m6s
Node.js CI / Test (16.x) (push) Successful in 9m56s
Node.js CI / Test (18.x) (push) Successful in 9m54s
Node.js CI / Lint (14.x) (push) Failing after 5m9s

Main

See merge request Binaryify/neteasecloudmusicapi!29
This commit is contained in:
binaryify 2024-10-20 13:23:44 +00:00
commit e84325625d
26 changed files with 477 additions and 49 deletions

View File

@ -435,6 +435,18 @@ banner({ type: 0 }).then((res) => {
289. 歌曲是否喜爱
290. 用户是否互相关注
291. 歌曲动态封面
292. 用户徽章
293. 用户状态
294. 用户状态 - 支持设置的状态
295. 用户状态 - 相同状态的用户
296. 用户状态 - 编辑
297. 听歌足迹 - 年度听歌足迹
298. 听歌足迹 - 今日收听
299. 听歌足迹 - 总收听时长
300. 听歌足迹 - 本周/本月收听时长
301. 听歌足迹 - 周/月/年收听报告
302. 歌单导入 - 元数据/文字/链接导入
303. 歌单导入 - 任务状态
## 单元测试

View File

@ -0,0 +1,11 @@
// 听歌足迹 - 本周/本月收听时长
const createOption = require('../util/option.js')
module.exports = (query, request) => {
return request(
`/api/content/activity/listen/data/realtime/report`,
{
type: query.type || 'week', //周 week 月 month
},
createOption(query),
)
}

View File

@ -0,0 +1,12 @@
// 听歌足迹 - 周/月/年收听报告
const createOption = require('../util/option.js')
module.exports = (query, request) => {
return request(
`/api/content/activity/listen/data/report`,
{
type: query.type || 'week', //周 week 月 month 年 year
endTime: query.endTime, // 不填就是本周/月的
},
createOption(query),
)
}

View File

@ -0,0 +1,9 @@
// 听歌足迹 - 今日收听
const createOption = require('../util/option.js')
module.exports = (query, request) => {
return request(
`/api/content/activity/listen/data/today/song/play/rank`,
{},
createOption(query),
)
}

View File

@ -0,0 +1,9 @@
// 听歌足迹 - 总收听时长
const createOption = require('../util/option.js')
module.exports = (query, request) => {
return request(
`/api/content/activity/listen/data/total`,
{},
createOption(query),
)
}

View File

@ -0,0 +1,9 @@
// 听歌足迹 - 年度听歌足迹
const createOption = require('../util/option.js')
module.exports = (query, request) => {
return request(
`/api/content/activity/listen/data/year/report`,
{},
createOption(query),
)
}

View File

@ -0,0 +1,62 @@
// 歌单导入 - 元数据/文字/链接导入
const createOption = require('../util/option.js')
module.exports = (query, request) => {
let data = {
importStarPlaylist: query.importStarPlaylist || false, // 导入我喜欢的音乐
}
if (query.local) {
// 元数据导入
let local = JSON.parse(query.local)
let multiSongs = JSON.stringify(
local.map(function (e) {
return {
songName: e.name,
artistName: e.artist,
albumName: e.album,
}
}),
)
data = {
...data,
multiSongs: multiSongs,
}
} else {
let playlistName = // 歌单名称
query.playlistName || '导入音乐 '.concat(new Date().toLocaleString())
let songs = ''
if (query.text) {
// 文字导入
songs = JSON.stringify([
{
name: playlistName,
type: '',
url: encodeURI('rpc://playlist/import?text='.concat(query.text)),
},
])
}
if (query.link) {
// 链接导入
let link = JSON.parse(query.link)
songs = JSON.stringify(
link.map(function (e) {
return { name: playlistName, type: '', url: encodeURI(e) }
}),
)
}
data = {
...data,
playlistName: playlistName,
createBusinessCode: undefined,
extParam: undefined,
taskIdForLog: '',
songs: songs,
}
}
return request(
`/api/playlist/import/name/task/create`,
data,
createOption(query),
)
}

View File

@ -0,0 +1,11 @@
// 歌单导入 - 任务状态
const createOption = require('../util/option.js')
module.exports = (query, request) => {
return request(
`/api/playlist/import/task/status/v2`,
{
taskIds: JSON.stringify([query.id]),
},
createOption(query),
)
}

11
module/user_medal.js Normal file
View File

@ -0,0 +1,11 @@
// 用户徽章
const createOption = require('../util/option.js')
module.exports = (query, request) => {
return request(
`/api/medal/user/page`,
{
uid: query.uid,
},
createOption(query),
)
}

View File

@ -0,0 +1,11 @@
// 用户状态
const createOption = require('../util/option.js')
module.exports = (query, request) => {
return request(
`/api/social/user/status`,
{
visitorId: query.uid,
},
createOption(query),
)
}

View File

@ -0,0 +1,16 @@
// 用户状态 - 编辑
const createOption = require('../util/option.js')
module.exports = (query, request) => {
return request(
`/api/social/user/status/edit`,
{
content: JSON.stringify({
type: query.type,
iconUrl: query.iconUrl,
content: query.content,
actionUrl: query.actionUrl,
}),
},
createOption(query),
)
}

View File

@ -0,0 +1,5 @@
// 用户状态 - 相同状态的用户
const createOption = require('../util/option.js')
module.exports = (query, request) => {
return request(`/api/social/user/status/rcmd`, {}, createOption(query))
}

View File

@ -0,0 +1,5 @@
// 用户状态 - 支持设置的状态
const createOption = require('../util/option.js')
module.exports = (query, request) => {
return request(`/api/social/user/status/support`, {}, createOption(query))
}

View File

@ -97,7 +97,7 @@
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://fastly.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
async function sendRequest() {
document.getElementById('result').value = ""

View File

@ -15,7 +15,7 @@
</div>
<input id="file" type="file" />
<img id="avatar" style="height: 200px; width: 200px; border-radius: 50%" />
<script src="https://cdn.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js
"></script>
<script>
main()

View File

@ -22,8 +22,8 @@
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
<script src="https://fastly.jsdelivr.net/npm/vue"></script>
<script>
const app = Vue.createApp({
data() {

View File

@ -307,6 +307,18 @@
289. 歌曲是否喜爱
290. 用户是否互相关注
291. 歌曲动态封面
292. 用户徽章
293. 用户状态
294. 用户状态 - 支持设置的状态
295. 用户状态 - 相同状态的用户
296. 用户状态 - 编辑
297. 听歌足迹 - 年度听歌足迹
298. 听歌足迹 - 今日收听
299. 听歌足迹 - 总收听时长
300. 听歌足迹 - 本周/本月收听时长
301. 听歌足迹 - 周/月/年收听报告
302. 歌单导入 - 元数据/文字/链接导入
303. 歌单导入 - 任务状态
## 安装
@ -4601,9 +4613,9 @@ qrCodeStatus:20,detailReason:0 验证成功qrCodeStatus:21,detailReason:0 二
`id`: 歌曲id
**接口地址:** `song/music/detail`
**接口地址:** `/song/music/detail`
**调用例子:** `song/music/detail?id=2082700997`
**调用例子:** `/song/music/detail?id=2082700997`
返回字段说明 :
```
@ -4806,7 +4818,7 @@ bitrate = Math.floor(br / 1000)
### 歌曲动态封面
说明 : 调用此接口, 传入歌曲id, 获取歌曲动态封面
说明 : 登录后调用此接口, 传入歌曲id, 获取歌曲动态封面
**必选参数 :**
@ -4816,6 +4828,167 @@ bitrate = Math.floor(br / 1000)
**调用例子 :** `/song/dynamic/cover?id=2101179024`
### 用户徽章
说明 : 调用此接口, 传入用户id, 获取用户徽章
**必选参数 :**
`uid`: 用户 id
**接口地址 :** `/user/medal`
**调用例子 :** `/user/medal?uid=32953014`
### 用户状态
说明 : 登录后调用此接口, 传入用户id, 获取用户状态
**必选参数 :**
`uid`: 用户 id
**接口地址 :** `/user/social/status`
**调用例子 :** `/user/social/status?uid=32953014`
### 用户状态 - 支持设置的状态
说明 : 登录后调用此接口, 获取支持设置的状态
**接口地址 :** `/user/social/status/support`
### 用户状态 - 相同状态的用户
说明 : 登录后调用此接口, 获取相同状态的用户
**接口地址 :** `/user/social/status/rcmd`
### 用户状态 - 编辑
说明 : 登录后调用此接口, 编辑当前用户状态, 所需参数可在接口`/user/social/status/support`获取
**接口地址 :** `/user/social/status/edit`
### 听歌足迹 - 年度听歌足迹
说明 : 登录后调用此接口, 获取年度听歌足迹
**接口地址 :** `/listen/data/year/report`
### 听歌足迹 - 今日收听
说明 : 登录后调用此接口, 获取今日收听
**接口地址 :** `/listen/data/today/song`
### 听歌足迹 - 总收听时长
说明 : 登录后调用此接口, 获取总收听时长; 相关接口可能需要vip权限
**接口地址 :** `/listen/data/total`
### 听歌足迹 - 本周/本月收听时长
说明 : 登录后调用此接口, 获取本周/本月收听时长
**必选参数 :**
`type`: 维度类型 周 week 月 month; 今年没结束,不支持今年的数据
**接口地址 :** `/listen/data/realtime/report`
**调用例子 :** `/listen/data/realtime/report?type=month`
### 听歌足迹 - 周/月/年收听报告
说明 : 登录后调用此接口, 获取周/月/年收听报告
**必选参数 :**
`type`: 维度类型 周 week 月 month 年 year
**可选参数 :**
`endTime` : 周: 每周周六0点的时间戳 月: 每月最后一天0点的时间戳 年: 每年最后一天0点的时间戳
不填就是本周/月的, 今年没结束,则没有今年的数据
**接口地址 :** `/listen/data/report`
**调用例子 :** `/listen/data/report?type=month`
### 歌单导入 - 元数据/文字/链接导入
说明 : 登录后调用此接口, 支持通过元数据/文字/链接三种方式生成歌单; 三种方式不可同时调用
**接口地址 :** `/playlist/import/name/task/create`
**可选参数 :**
`importStarPlaylist` : 是否导入`我喜欢的音乐`
**元数据导入 :**
`local`: json类型的字符串, 如:
```javascript
let local = encodeURIComponent(
JSON.stringify([
{
name: 'アイニーブルー', // 歌曲名称
artist: 'ZLMS', // 艺术家名称
album: 'アイニーブルー',// 专辑名称
},
{
name: 'ファンタズマ',
artist: 'sasakure.UK',
album: '未来イヴ',
},
]),
)
```
**调用例子 :** `/playlist/import/name/task/create?local=${local}`
**文字导入 :**
`text`: 导入的文字, 如:
```javascript
let text = encodeURIComponent(`アイニーブルー ZLMS
ファンタズマ sasakure.UK`)
```
**调用例子 :** `/playlist/import/name/task/create?text=${text}`
**链接导入 :**
`link`: 存有歌单链接的数组类型的字符串, 如:
```javascript
let link = encodeURIComponent(
JSON.stringify([
'https://i.y.qq.com/n2/m/share/details/taoge.html?id=7716341988&hosteuin=',
'https://i.y.qq.com/n2/m/share/details/taoge.html?id=8010042041&hosteuin=',
]),
)
```
歌单链接来源:
1. 将歌单分享到微信/微博/QQ后复制链接
2. 直接复制歌单/个人主页链接
3. 直接复制文章链接
**调用例子 :** `/playlist/import/name/task/create?link=${link}`
### 歌单导入 - 任务状态
说明: 调用此接口, 传入导入歌单任务id, 获取任务状态
**必选参数:**
`id`: 任务id
**接口地址:** `/playlist/import/task/status`
**调用例子:** `/playlist/import/task/status?id=123834369`
## 离线访问此文档
此文档同时也是 Progressive Web Apps(PWA), 加入了 serviceWorker, 可离线访问

View File

@ -35,8 +35,8 @@
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@3"></script>
<script src="https://fastly.jsdelivr.net/npm/axios"></script>
<script src="https://fastly.jsdelivr.net/npm/vue@3"></script>
<script>
const app = Vue.createApp({

View File

@ -13,7 +13,7 @@
如果没登录,请先登录
</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
<script>
async function main() {
const res = await axios({

View File

@ -6,58 +6,130 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>网易云音乐 API</title>
</head>
<body>
<h1>网易云音乐 API</h1>
当你看到这个页面时,这个服务已经成功跑起来了~
<a href="/docs">查看文档</a>
<h2>例子:</h2>
<ul>
<li>1. <a href="./search?keywords=海阔天空">搜索</a></li>
<li>2. <a href="./comment/music?id=186016&limit=1">歌曲评论</a></li>
<li>3. <a href="./dj/program?rid=336355127">电台节目</a></li>
<li>4. <a href="./qrlogin.html">二维码登录</a></li>
<li>4. <a href="./audio_match_demo/index.html">听歌识曲</a></li>
<li>5. <a href="./cloud.html">云盘上传</a></li>
<li>6. <a href="./eapi_decrypt.html">eapi 参数和返回内容解析</a></li>
<li>7. <a href="./api.html">API 调试界面</a></li>
</ul>
<style>
html,
body {
html, body {
height: 100vh;
width: 100vw;
margin: 0;
padding: 0;
background: #ffffff;
text-align: center;
margin-top: 30px;
overflow: hidden;
background: #f9f9f9;
font-family: Arial, sans-serif;
color: #333;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
* {
color: rgb(100, 100, 100);
h1 {
font-size: 2.5em;
margin-bottom: 1em;
color: #42b983;
}
p {
font-size: 1.2em;
margin-bottom: 2em;
color: #666;
}
a {
color: #42b983;
text-decoration: none;
transition: color 0.3s ease;
}
ul,
li {
margin: 0;
a:hover {
color: #329d6e;
}
ul {
margin-left: -40px;
line-height: 30px;
list-style: none;
padding: 0;
margin: 0;
text-align: left;
max-width: 600px;
width: 100%;
}
li {
list-style: none;
margin: 0.5em 0;
line-height: 1.5;
display: flex;
align-items: center;
}
.number {
margin-right: 10px;
color: #999;
font-weight: bold;
}
.container {
background: #fff;
padding: 2em;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
max-height: 80vh; /* 设置最大高度 */
overflow-y: auto; /* 启用垂直滚动条 */
}
.version {
margin-top: 0.5em;
font-size: 1.0em;
color: #666;
}
</style>
</head>
<body>
<div class="container">
<h1>网易云音乐 API <span id="api-version"></span></h1>
<p>当你看到这个页面时,这个服务已经成功跑起来了~</p>
<p class="current-url"><span id="current-url"></span></p>
<a href="/docs">查看文档</a>
<h2>例子:</h2>
<ul id="example-list">
<li><a href="./search?keywords=海阔天空">搜索</a></li>
<li><a href="./comment/music?id=186016&limit=1">歌曲评论</a></li>
<li><a href="./dj/program?rid=336355127">电台节目</a></li>
<li><a href="./qrlogin.html">二维码登录</a></li>
<li><a href="./audio_match_demo/index.html">听歌识曲</a></li>
<li><a href="./cloud.html">云盘上传</a></li>
<li><a href="./eapi_decrypt.html">eapi 参数/返回值解析</a></li>
<li><a href="./api.html">API 调试界面</a></li>
</ul>
</div>
<script src="https://fastly.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const currentUrlElement = document.getElementById('current-url');
currentUrlElement.textContent = window.location.href;
const exampleList = document.getElementById('example-list');
const items = exampleList.getElementsByTagName('li');
for (let i = 0; i < items.length; i++) {
const number = document.createElement('span');
number.className = 'number';
number.textContent = (i + 1) + '. ';
items[i].prepend(number);
}
// 获取API版本号
axios({
url: '/inner/version',
method: 'post',
data: {},
}).then((res) => {
const body = res.data;
const version = body.data.version;
const apiVersionElement = document.getElementById('api-version');
apiVersionElement.textContent = ` v${version}`;
});
});
</script>
</body>
</html>
</html>

View File

@ -7,7 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>一起听</title>
<script src="https://unpkg.com/petite-vue"></script>
<script src="https://cdn.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/mdui@1.0.2/dist/css/mdui.min.css" />
<script src="https://unpkg.com/mdui@1.0.2/dist/js/mdui.min.js"></script>
</head>

View File

@ -8,7 +8,7 @@
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
<script>
const phone = '' // 这里填手机号
const password = '' // 这里填密码

View File

@ -15,7 +15,7 @@
</div>
<input id="file" type="file" name="filename" />
<img id="playlist_cover" style="height: 200px; width: 200px; border-radius: 50%" />
<script src="https://cdn.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
<script>
const playlist_id = ''
if (!playlist_id) {

View File

@ -10,7 +10,7 @@
<body>
<img id="qrImg" />
<div id="info" class="info"></div>
<script src="https://cdn.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js
"></script>
<script>

View File

@ -10,7 +10,7 @@
<body>
<img id="qrImg" />
<div id="info" class="info"></div>
<script src="https://cdn.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js
"></script>
<script>
async function login() {

View File

@ -33,8 +33,8 @@
</div>
<script src="https://cdn.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
<script src="https://fastly.jsdelivr.net/npm/vue"></script>
<script>
Vue.createApp({
data() {