Update
Some checks failed
Update Docker Hub Description / dockerHubDescription (push) Has been cancelled
Node.js CI / Test (14.x) (push) Has been cancelled
Node.js CI / Test (16.x) (push) Has been cancelled
Node.js CI / Test (18.x) (push) Has been cancelled
Node.js CI / Lint (14.x) (push) Has been cancelled
Some checks failed
Update Docker Hub Description / dockerHubDescription (push) Has been cancelled
Node.js CI / Test (14.x) (push) Has been cancelled
Node.js CI / Test (16.x) (push) Has been cancelled
Node.js CI / Test (18.x) (push) Has been cancelled
Node.js CI / Lint (14.x) (push) Has been cancelled
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
!/module
|
||||
!/plugins
|
||||
!/public
|
||||
!/static
|
||||
!/util
|
||||
!/app.js
|
||||
!/server.js
|
||||
!/package.json
|
||||
!/package-lock.json
|
||||
!/index.js
|
||||
!/generateConfig.js
|
||||
!/main.js
|
||||
!/data
|
||||
@@ -1,34 +0,0 @@
|
||||
|
||||
# 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
|
||||
57
.eslintrc.js
57
.eslintrc.js
@@ -1,57 +0,0 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
|
||||
ignorePatterns: ['public/'],
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint',
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['html'],
|
||||
extends: ['plugin:prettier/recommended'],
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
},
|
||||
|
||||
rules: {
|
||||
'prettier/prettier': [
|
||||
'error',
|
||||
{
|
||||
endOfLine: 'auto',
|
||||
},
|
||||
],
|
||||
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',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
10
.gitignore
vendored
10
.gitignore
vendored
@@ -1,10 +0,0 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
*.log
|
||||
.idea
|
||||
.vscode
|
||||
.history
|
||||
examples/moddef.json
|
||||
bin
|
||||
anonymous_token
|
||||
.vercel
|
||||
@@ -1 +0,0 @@
|
||||
node_modules
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"semi": false,
|
||||
"trailingComma": "all",
|
||||
"singleQuote": true
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- 12
|
||||
1390
CHANGELOG.MD
1390
CHANGELOG.MD
File diff suppressed because it is too large
Load Diff
16
Dockerfile
16
Dockerfile
@@ -1,16 +0,0 @@
|
||||
FROM node:lts-alpine
|
||||
|
||||
RUN apk add --no-cache tini
|
||||
|
||||
ENV NODE_ENV production
|
||||
USER node
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --chown=node:node . ./
|
||||
|
||||
RUN yarn --network-timeout=100000
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
CMD [ "/sbin/tini", "--", "node", "app.js" ]
|
||||
@@ -453,6 +453,11 @@ banner({ type: 0 }).then((res) => {
|
||||
307. 歌词摘录 - 我的歌词本
|
||||
308. 歌词摘录 - 添加/修改摘录歌词
|
||||
309. 歌词摘录 - 删除摘录歌词
|
||||
310. 广播电台 - 分类/地区信息
|
||||
311. 广播电台 - 我的收藏
|
||||
312. 广播电台 - 电台信息
|
||||
313. 广播电台 - 全部电台
|
||||
314. 广播电台 - 收藏/取消收藏电台
|
||||
|
||||
## 单元测试
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
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()
|
||||
@@ -1,29 +0,0 @@
|
||||
## 环境
|
||||
- 系统/平台: <你的系统和平台>
|
||||
|
||||
- nodejs 版本: <你的 NodeJS 版本号>
|
||||
|
||||
- API版本:<运行的云音乐 API 的版本号, 对应 package.json 里面的 version>
|
||||
|
||||
## 出现问题
|
||||
<出现的问题>
|
||||
|
||||
## 重现步骤
|
||||
<重现步骤>
|
||||
|
||||
## 期待效果
|
||||
<现在的效果,期待的效果>
|
||||
|
||||
|
||||
|
||||
>先看文档有没有相关说明,调用前须知必看
|
||||
|
||||
>先在 issues 搜一下是否有相似问题,没有再发,否则直接关闭
|
||||
|
||||
>不处理别人搭建的线上服务的问题,此项目不提供任何线上服务,请自行搭建
|
||||
|
||||
>重现步骤尽量详细,不能含糊不清,包含请求地址和对应参数以及操作过程描述,不是每个人都喜欢猜别人遇到了什么问题和找参数一个个试,也比较浪费时间
|
||||
|
||||
>如果不是提建议,提 issues 如果不照着模版来将不会优先处理或直接关闭
|
||||
|
||||
>460 cheating 的问题把 `util/request.js` 里面的 `headers['X-Real-IP']` 的注释取消掉就好
|
||||
18
main.test.js
18
main.test.js
@@ -1,18 +0,0 @@
|
||||
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')
|
||||
})
|
||||
})
|
||||
11
module/broadcast_category_region_get.js
Normal file
11
module/broadcast_category_region_get.js
Normal file
@@ -0,0 +1,11 @@
|
||||
// 广播电台 - 分类/地区信息
|
||||
|
||||
const createOption = require('../util/option.js')
|
||||
module.exports = (query, request) => {
|
||||
const data = {}
|
||||
return request(
|
||||
`/api/voice/broadcast/category/region/get`,
|
||||
data,
|
||||
createOption(query),
|
||||
)
|
||||
}
|
||||
12
module/broadcast_channel_collect_list.js
Normal file
12
module/broadcast_channel_collect_list.js
Normal file
@@ -0,0 +1,12 @@
|
||||
// 广播电台 - 我的收藏
|
||||
|
||||
const createOption = require('../util/option.js')
|
||||
module.exports = (query, request) => {
|
||||
const data = {
|
||||
contentType: 'BROADCAST',
|
||||
limit: query.limit || '99999',
|
||||
timeReverseOrder: 'true',
|
||||
startDate: '4762584922000',
|
||||
}
|
||||
return request(`/api/content/channel/collect/list`, data, createOption(query))
|
||||
}
|
||||
13
module/broadcast_channel_currentinfo.js
Normal file
13
module/broadcast_channel_currentinfo.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// 广播电台 - 电台信息
|
||||
|
||||
const createOption = require('../util/option.js')
|
||||
module.exports = (query, request) => {
|
||||
const data = {
|
||||
channelId: query.id,
|
||||
}
|
||||
return request(
|
||||
`/api/voice/broadcast/channel/currentinfo`,
|
||||
data,
|
||||
createOption(query),
|
||||
)
|
||||
}
|
||||
13
module/broadcast_channel_list.js
Normal file
13
module/broadcast_channel_list.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// 广播电台 - 全部电台
|
||||
|
||||
const createOption = require('../util/option.js')
|
||||
module.exports = (query, request) => {
|
||||
const data = {
|
||||
categoryId: query.categoryId || '0',
|
||||
regionId: query.regionId || '0',
|
||||
limit: query.limit || '20',
|
||||
lastId: query.lastId || '0',
|
||||
score: query.score || '-1',
|
||||
}
|
||||
return request(`/api/voice/broadcast/channel/list`, data, createOption(query))
|
||||
}
|
||||
12
module/broadcast_sub.js
Normal file
12
module/broadcast_sub.js
Normal file
@@ -0,0 +1,12 @@
|
||||
// 广播电台 - 收藏/取消收藏电台
|
||||
|
||||
const createOption = require('../util/option.js')
|
||||
module.exports = (query, request) => {
|
||||
query.t = query.t == 1 ? 'false' : 'true'
|
||||
const data = {
|
||||
contentType: 'BROADCAST',
|
||||
contentId: query.id,
|
||||
cancelCollect: query.t,
|
||||
}
|
||||
return request(`/api/content/interact/collect`, data, createOption(query))
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
const { avatar_upload, login_cellphone } = require('../main')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
async function main() {
|
||||
const result = await login_cellphone({
|
||||
phone: '手机号',
|
||||
password: '密码',
|
||||
})
|
||||
const filePath = './test.jpg'
|
||||
await avatar_upload({
|
||||
imgFile: {
|
||||
name: path.basename(filePath),
|
||||
data: fs.readFileSync(filePath),
|
||||
},
|
||||
imgSize: 1012, //图片尺寸,需要正方形图片
|
||||
cookie: result.body.cookie,
|
||||
})
|
||||
}
|
||||
main()
|
||||
@@ -1,15 +0,0 @@
|
||||
const { eapiResDecrypt, eapiReqDecrypt } = require('../util/crypto')
|
||||
|
||||
let reqParamsHex =
|
||||
'6E0B1C712DCB3648589D7C950C296204072A88C3E080C4CFFD0A71A553EC2533BA88E11B1E1C6DF3BE8EFA26177FCB6FCA34EB3FAFAB4671B2BBAFA9781AFDA2BF53A3DC423722493837B9BC6E80CED5BBD2DDC2856920E4D4E3E7F3EB77ECF265217A66AE677BE36F2D6FB203F721CA250E1453EA61A34904E33D5FCB9D483601D744BE0AE979AC911A00F25828538844F4B1C24F6C34880A4AB257F530C7FB10A81FED32B18D09D70C0B1B9D34A2E58A3C3FAD382C6F958077059C4F801AD7B3B248FDB9D7A59B6A9EEFF8C781A84315B33A7AFD48BE9FCFCBE1902CCC27949ACF2BDE3FA34D116E230C3597E8320B8C42BBBF371A00C03EC428E0440EB94C1540F3FD4173D29E310AFE43AB0EF449852904103EF305FC435AD43B7D8673642F74C89CCB2F1A6A79B3BE14F1235D3843C3B241D12C05DBDDF37B68CA8B5D0230AF1FCF2A9705886F4D126B33FFF6948DE1E4046DB6423D687E96C5B65122464D2E71AEC7722935FF2C3796FAE253A16AA3B102FBE7296AB0DB9EA5C46AD12B'.replaceAll(
|
||||
' ',
|
||||
'',
|
||||
)
|
||||
const resHex =
|
||||
`FB A2 DB 80 DF 26 69 F1 AA 14 81 8E 56 93 53 A6 44 9C 10 70 26 65 59 64 AE 09 02 75 56 65 1C 98 E6 DC E7 50 F1 6E 64 78 BC 87 B8 0E 6D 52 B0 23`.replaceAll(
|
||||
' ',
|
||||
'',
|
||||
)
|
||||
console.log(reqParamsHex)
|
||||
console.log(eapiReqDecrypt(reqParamsHex))
|
||||
console.log(eapiResDecrypt(resHex))
|
||||
@@ -1,104 +0,0 @@
|
||||
const { cloud, login_cellphone } = require('../main')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const yargs = require('yargs')
|
||||
|
||||
const MUSIC_FILE_EXTENSIONS = new Set(['.mp3', '.flac'])
|
||||
|
||||
function getAllMusicFiles(dir, arrayOfFiles) {
|
||||
arrayOfFiles = arrayOfFiles || []
|
||||
|
||||
fs.readdirSync(dir).forEach((file) => {
|
||||
let fullPath = path.join(dir, file)
|
||||
if (fs.lstatSync(fullPath).isDirectory()) {
|
||||
getAllMusicFiles(fullPath, arrayOfFiles)
|
||||
} else {
|
||||
if (MUSIC_FILE_EXTENSIONS.has(path.extname(fullPath))) {
|
||||
arrayOfFiles.push(fullPath)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return arrayOfFiles
|
||||
}
|
||||
|
||||
async function uploadArrayOfFile(token, arrayOfFiles) {
|
||||
let failedFiles = []
|
||||
let failed = 0
|
||||
const fileCount = arrayOfFiles.length
|
||||
for (let k in arrayOfFiles) {
|
||||
const file = arrayOfFiles[k]
|
||||
try {
|
||||
await cloud({
|
||||
songFile: {
|
||||
name: path.basename(file),
|
||||
data: fs.readFileSync(file),
|
||||
},
|
||||
cookie: token.body.cookie,
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
failed += 1
|
||||
failedFiles.push(file)
|
||||
}
|
||||
console.log(`Uploaded ${k + 1}/${fileCount} songs`)
|
||||
}
|
||||
return { failedFiles, failed }
|
||||
}
|
||||
|
||||
function getParsedArgs() {
|
||||
return yargs(process.argv.slice(2))
|
||||
.option('country_code', {
|
||||
default: '86',
|
||||
describe: 'The country code of your phone number',
|
||||
type: 'string',
|
||||
})
|
||||
.option('phone_number', {
|
||||
demandOption: true,
|
||||
describe: 'Your phone number',
|
||||
type: 'string',
|
||||
})
|
||||
.option('password', {
|
||||
demandOption: true,
|
||||
describe: 'Your password',
|
||||
type: 'string',
|
||||
})
|
||||
.option('file', {
|
||||
describe: 'The absolute path to the single music file to be uploaded',
|
||||
type: 'string',
|
||||
})
|
||||
.option('dir', {
|
||||
describe: 'The absolute to the directory of music files to be uploaded',
|
||||
type: 'string',
|
||||
})
|
||||
.conflicts('file', 'dir')
|
||||
.help()
|
||||
.alias('help', 'h').argv
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const args = getParsedArgs()
|
||||
const token = await login_cellphone({
|
||||
countrycode: args.country_code,
|
||||
phone: args.phone_number,
|
||||
password: args.password,
|
||||
})
|
||||
const files = args.file ? [args.file] : getAllMusicFiles(args.dir)
|
||||
const fileCount = files.length
|
||||
|
||||
console.log(`Found ${fileCount} files, uploading...`)
|
||||
let res = await uploadArrayOfFile(token, files)
|
||||
if (res.failed) {
|
||||
console.log(`Failed to upload ${res.failed} songs, retrying...`)
|
||||
res = await uploadArrayOfFile(token, res.failedFiles)
|
||||
}
|
||||
|
||||
console.log(`Uploaded ${fileCount - res.failed} songs`)
|
||||
console.log(
|
||||
`Failed to upload ${res.failed} songs, you can reupload the files below`,
|
||||
)
|
||||
for (let k in res.failedFiles) {
|
||||
console.log(res.failedFiles[k])
|
||||
}
|
||||
}
|
||||
main()
|
||||
@@ -1,23 +0,0 @@
|
||||
const { cloud, login_cellphone } = require('../main')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
async function main() {
|
||||
const result = await login_cellphone({
|
||||
phone: '手机号',
|
||||
password: '密码',
|
||||
})
|
||||
const filePath = './test.mp3'
|
||||
try {
|
||||
await cloud({
|
||||
songFile: {
|
||||
name: path.basename(filePath),
|
||||
data: fs.readFileSync(filePath),
|
||||
},
|
||||
cookie: result.body.cookie,
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error, 'error')
|
||||
}
|
||||
}
|
||||
main()
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 125 KiB |
@@ -1,31 +0,0 @@
|
||||
const {
|
||||
login_cellphone,
|
||||
user_cloud,
|
||||
album_sublist,
|
||||
song_url,
|
||||
} = require('../main')
|
||||
async function test() {
|
||||
try {
|
||||
const result = await login_cellphone({
|
||||
phone: '手机号',
|
||||
password: '密码',
|
||||
})
|
||||
console.log(result)
|
||||
const result2 = await user_cloud({
|
||||
cookie: result.body.cookie,
|
||||
})
|
||||
console.log(result2.body)
|
||||
const result3 = await album_sublist({
|
||||
cookie: result.body.cookie,
|
||||
})
|
||||
console.log(result3.body)
|
||||
const result4 = await song_url({
|
||||
cookie: result.body.cookie,
|
||||
id: 33894312,
|
||||
})
|
||||
console.log(result4.body)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
test()
|
||||
Binary file not shown.
@@ -1,9 +0,0 @@
|
||||
import { banner, lyric } from 'NeteaseCloudMusicApi'
|
||||
banner({ type: 0 }).then((res) => {
|
||||
console.log(res)
|
||||
})
|
||||
lyric({
|
||||
id: '33894312',
|
||||
}).then((res) => {
|
||||
console.log(res)
|
||||
})
|
||||
17
node_modules/.bin/NeteaseCloudMusicApi
generated
vendored
Executable file
17
node_modules/.bin/NeteaseCloudMusicApi
generated
vendored
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/NeteaseCloudMusicApi@4.27.0_7cd87476f665b4f82bd82cd82a10336d/node_modules/NeteaseCloudMusicApi/node_modules:/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/NeteaseCloudMusicApi@4.27.0_7cd87476f665b4f82bd82cd82a10336d/node_modules:/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/NeteaseCloudMusicApi@4.27.0_7cd87476f665b4f82bd82cd82a10336d/node_modules/NeteaseCloudMusicApi/node_modules:/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/NeteaseCloudMusicApi@4.27.0_7cd87476f665b4f82bd82cd82a10336d/node_modules:/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../../app.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../../app.js" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/qrcode
generated
vendored
Executable file
17
node_modules/.bin/qrcode
generated
vendored
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/bin/node_modules:/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/node_modules:/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/qrcode@1.5.4/node_modules:/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/bin/node_modules:/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/node_modules:/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/qrcode@1.5.4/node_modules:/Users/kudzues/Downloads/未命名文件夹/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../../../../../qrcode@1.5.4/node_modules/qrcode/bin/qrcode" "$@"
|
||||
else
|
||||
exec node "$basedir/../../../../../qrcode@1.5.4/node_modules/qrcode/bin/qrcode" "$@"
|
||||
fi
|
||||
11051
package-lock.json
generated
11051
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "NeteaseCloudMusicApi",
|
||||
"version": "4.25.0",
|
||||
"version": "4.27.0",
|
||||
"description": "网易云音乐 NodeJS 版 API",
|
||||
"scripts": {
|
||||
"start": "node app.js",
|
||||
|
||||
@@ -325,6 +325,11 @@
|
||||
307. 歌词摘录 - 我的歌词本
|
||||
308. 歌词摘录 - 添加/修改摘录歌词
|
||||
309. 歌词摘录 - 删除摘录歌词
|
||||
310. 广播电台 - 分类/地区信息
|
||||
311. 广播电台 - 我的收藏
|
||||
312. 广播电台 - 电台信息
|
||||
313. 广播电台 - 全部电台
|
||||
314. 广播电台 - 收藏/取消收藏电台
|
||||
|
||||
## 安装
|
||||
|
||||
@@ -5086,6 +5091,52 @@ let data = encodeURIComponent(
|
||||
|
||||
**调用例子:** `/song/lyrics/mark?id=2083850`
|
||||
|
||||
### 广播电台 - 分类/地区信息
|
||||
|
||||
说明: 调用此接口, 获取广播电台 - 分类/地区信息
|
||||
|
||||
**接口地址:** `/broadcast/category/region/get`
|
||||
|
||||
**调用例子:** `/broadcast/category/region/get`
|
||||
|
||||
### 广播电台 - 我的收藏
|
||||
|
||||
说明: 调用此接口, 获取广播电台 - 我的收藏
|
||||
|
||||
**可选参数 :**
|
||||
|
||||
`limit` : 返回数量 , 默认为 99999
|
||||
|
||||
**接口地址:** `/broadcast/channel/collect/list`
|
||||
|
||||
**调用例子:** `/broadcast/channel/collect/list`
|
||||
|
||||
### 广播电台 - 电台信息
|
||||
|
||||
说明: 调用此接口, 传入电台id, 获取广播电台 - 电台信息
|
||||
|
||||
**必选参数:**
|
||||
|
||||
`id`: 电台id
|
||||
|
||||
**接口地址:** `/broadcast/channel/currentinfo`
|
||||
|
||||
**调用例子:** `/broadcast/channel/currentinfo?id=5`
|
||||
|
||||
### 广播电台 - 全部电台
|
||||
|
||||
说明: 调用此接口, 获取广播电台 - 全部电台
|
||||
|
||||
**可选参数 :**
|
||||
|
||||
`categoryId` : 类别id, 默认为 0,可从“广播电台 - 分类/地区信息”接口获取
|
||||
|
||||
`regionId` : 地区id, 默认为 0,可从“广播电台 - 分类/地区信息”接口获取
|
||||
|
||||
**接口地址:** `/broadcast/channel/list`
|
||||
|
||||
**调用例子:** `/broadcast/channel/list`
|
||||
|
||||
## 离线访问此文档
|
||||
|
||||
此文档同时也是 Progressive Web Apps(PWA), 加入了 serviceWorker, 可离线访问
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"config:base",
|
||||
"helpers:pinGitHubActionDigests"
|
||||
]
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
export PORT=9000
|
||||
/var/lang/node16/bin/node app.js
|
||||
@@ -1,37 +0,0 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const tmpPath = require('os').tmpdir()
|
||||
/** @type {import("express").Express & serverMod.ExpressExtension} */
|
||||
let app
|
||||
if (!fs.existsSync(path.resolve(tmpPath, 'anonymous_token'))) {
|
||||
fs.writeFileSync(path.resolve(tmpPath, 'anonymous_token'), '', 'utf-8')
|
||||
}
|
||||
const serverMod = require('./server')
|
||||
before(async () => {
|
||||
const generateConfig = require('./generateConfig')
|
||||
await generateConfig()
|
||||
app = await serverMod.serveNcmApi({})
|
||||
|
||||
if (app.server && app.server.address) {
|
||||
const addr = app.server.address()
|
||||
if (addr && typeof addr === 'object' && 'port' in addr) {
|
||||
global.host = `http://localhost:${addr.port}`
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('failed to set up host')
|
||||
})
|
||||
|
||||
after((done) => {
|
||||
if (app.server) {
|
||||
app.server.close(done)
|
||||
return
|
||||
}
|
||||
|
||||
throw new Error('failed to set up server')
|
||||
})
|
||||
|
||||
fs.readdirSync(path.join(__dirname, 'test')).forEach((file) => {
|
||||
require(path.join(__dirname, 'test', file))
|
||||
})
|
||||
@@ -1,25 +0,0 @@
|
||||
const assert = require('assert')
|
||||
const { default: axios } = require('axios')
|
||||
const host = global.host || 'http://localhost:3000'
|
||||
describe('测试获取歌手专辑列表是否正常', () => {
|
||||
it('数据的 code 应该为200', (done) => {
|
||||
const qs = {
|
||||
id: 32311,
|
||||
realIP: global.cnIp,
|
||||
}
|
||||
|
||||
axios
|
||||
.get(`${host}/album`, {
|
||||
params: qs,
|
||||
})
|
||||
.then(({ status, data }) => {
|
||||
if (status == 200) {
|
||||
assert(data.code === 200)
|
||||
}
|
||||
done()
|
||||
})
|
||||
.catch((err) => {
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,25 +0,0 @@
|
||||
const assert = require('assert')
|
||||
const { default: axios } = require('axios')
|
||||
const host = global.host || 'http://localhost:3000'
|
||||
describe('测试获取评论是否正常', () => {
|
||||
it('数据的 code 应该为200', (done) => {
|
||||
const qs = {
|
||||
id: 32311,
|
||||
realIP: global.cnIp,
|
||||
}
|
||||
|
||||
axios
|
||||
.get(`${host}/comment/album`, {
|
||||
params: qs,
|
||||
})
|
||||
.then(({ status, data }) => {
|
||||
if (status == 200) {
|
||||
assert(data.code === 200)
|
||||
}
|
||||
done()
|
||||
})
|
||||
.catch((err) => {
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,25 +0,0 @@
|
||||
const assert = require('assert')
|
||||
const { default: axios } = require('axios')
|
||||
const host = global.host || 'http://localhost:3000'
|
||||
describe('测试获取歌词是否正常', () => {
|
||||
it('数据应该有 lrc 字段', (done) => {
|
||||
const qs = {
|
||||
id: 347230,
|
||||
realIP: global.cnIp,
|
||||
}
|
||||
|
||||
axios
|
||||
.get(`${host}/lyric`, {
|
||||
params: qs,
|
||||
})
|
||||
.then(({ status, data }) => {
|
||||
if (status == 200) {
|
||||
assert(typeof data.lrc !== 'undefined')
|
||||
}
|
||||
done()
|
||||
})
|
||||
.catch((err) => {
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,26 +0,0 @@
|
||||
const assert = require('assert')
|
||||
const { default: axios } = require('axios')
|
||||
const host = global.host || 'http://localhost:3000'
|
||||
describe('测试获取歌曲是否正常', () => {
|
||||
it('歌曲的 url 不应该为空', (done) => {
|
||||
const qs = {
|
||||
id: 464315036,
|
||||
br: 999000,
|
||||
realIP: global.cnIp,
|
||||
}
|
||||
|
||||
axios
|
||||
.get(`${host}/song/url`, {
|
||||
params: qs,
|
||||
})
|
||||
.then(({ status, data }) => {
|
||||
if (status == 200) {
|
||||
assert(!!data.data[0].url)
|
||||
}
|
||||
done()
|
||||
})
|
||||
.catch((err) => {
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,25 +0,0 @@
|
||||
const assert = require('assert')
|
||||
const { default: axios } = require('axios')
|
||||
const host = global.host || 'http://localhost:3000'
|
||||
describe('测试搜索是否正常', () => {
|
||||
it('获取到的数据的 name 应该和搜索关键词一致', (done) => {
|
||||
const qs = {
|
||||
keywords: '海阔天空',
|
||||
type: 1,
|
||||
realIP: global.cnIp,
|
||||
}
|
||||
axios
|
||||
.get(`${host}/search`, {
|
||||
params: qs,
|
||||
})
|
||||
.then(({ status, data }) => {
|
||||
if (status == 200) {
|
||||
assert(data.result.songs[0].name === '海阔天空')
|
||||
}
|
||||
done()
|
||||
})
|
||||
.catch((err) => {
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2015",
|
||||
"module": "commonjs",
|
||||
"experimentalDecorators": true,
|
||||
"moduleResolution": "node",
|
||||
"lib": [
|
||||
"esnext",
|
||||
"esnext.asynciterable",
|
||||
"dom"
|
||||
],
|
||||
"esModuleInterop": true,
|
||||
"allowJs": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"~/*": [
|
||||
"./*"
|
||||
],
|
||||
"@/*": [
|
||||
"./*"
|
||||
]
|
||||
},
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
@@ -183,13 +183,13 @@ const createRequest = (uri, data, options) => {
|
||||
if (crypto === 'eapi') {
|
||||
// 使用eapi加密
|
||||
data.header = header
|
||||
data.e_r =
|
||||
options.e_r != undefined
|
||||
data.e_r = toBoolean(
|
||||
options.e_r !== undefined
|
||||
? options.e_r
|
||||
: data.e_r != undefined
|
||||
: data.e_r !== undefined
|
||||
? data.e_r
|
||||
: APP_CONF.encryptResponse // 用于加密接口返回值
|
||||
data.e_r = toBoolean(data.e_r)
|
||||
: APP_CONF.encryptResponse,
|
||||
) // 用于加密接口返回值
|
||||
encryptData = encrypt.eapi(uri, data)
|
||||
url = APP_CONF.apiDomain + '/eapi/' + uri.substr(5)
|
||||
} else if (crypto === 'api') {
|
||||
@@ -259,7 +259,7 @@ const createRequest = (uri, data, options) => {
|
||||
x.replace(/\s*Domain=[^(;|$)]+;*/, ''),
|
||||
)
|
||||
try {
|
||||
if (data.e_r) {
|
||||
if (crypto === 'eapi' && data.e_r) {
|
||||
// eapi接口返回值被加密,需要解密
|
||||
answer.body = encrypt.eapiResDecrypt(
|
||||
body.toString('hex').toUpperCase(),
|
||||
|
||||
15
vercel.json
15
vercel.json
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{
|
||||
"src": "./index.js",
|
||||
"use": "@vercel/node"
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"src": "/(.*)",
|
||||
"dest": "/"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user