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. 歌词摘录 - 我的歌词本
|
307. 歌词摘录 - 我的歌词本
|
||||||
308. 歌词摘录 - 添加/修改摘录歌词
|
308. 歌词摘录 - 添加/修改摘录歌词
|
||||||
309. 歌词摘录 - 删除摘录歌词
|
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",
|
"name": "NeteaseCloudMusicApi",
|
||||||
"version": "4.25.0",
|
"version": "4.27.0",
|
||||||
"description": "网易云音乐 NodeJS 版 API",
|
"description": "网易云音乐 NodeJS 版 API",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node app.js",
|
"start": "node app.js",
|
||||||
|
|||||||
@@ -325,6 +325,11 @@
|
|||||||
307. 歌词摘录 - 我的歌词本
|
307. 歌词摘录 - 我的歌词本
|
||||||
308. 歌词摘录 - 添加/修改摘录歌词
|
308. 歌词摘录 - 添加/修改摘录歌词
|
||||||
309. 歌词摘录 - 删除摘录歌词
|
309. 歌词摘录 - 删除摘录歌词
|
||||||
|
310. 广播电台 - 分类/地区信息
|
||||||
|
311. 广播电台 - 我的收藏
|
||||||
|
312. 广播电台 - 电台信息
|
||||||
|
313. 广播电台 - 全部电台
|
||||||
|
314. 广播电台 - 收藏/取消收藏电台
|
||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
||||||
@@ -5086,6 +5091,52 @@ let data = encodeURIComponent(
|
|||||||
|
|
||||||
**调用例子:** `/song/lyrics/mark?id=2083850`
|
**调用例子:** `/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, 可离线访问
|
此文档同时也是 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') {
|
if (crypto === 'eapi') {
|
||||||
// 使用eapi加密
|
// 使用eapi加密
|
||||||
data.header = header
|
data.header = header
|
||||||
data.e_r =
|
data.e_r = toBoolean(
|
||||||
options.e_r != undefined
|
options.e_r !== undefined
|
||||||
? options.e_r
|
? options.e_r
|
||||||
: data.e_r != undefined
|
: data.e_r !== undefined
|
||||||
? data.e_r
|
? data.e_r
|
||||||
: APP_CONF.encryptResponse // 用于加密接口返回值
|
: APP_CONF.encryptResponse,
|
||||||
data.e_r = toBoolean(data.e_r)
|
) // 用于加密接口返回值
|
||||||
encryptData = encrypt.eapi(uri, data)
|
encryptData = encrypt.eapi(uri, data)
|
||||||
url = APP_CONF.apiDomain + '/eapi/' + uri.substr(5)
|
url = APP_CONF.apiDomain + '/eapi/' + uri.substr(5)
|
||||||
} else if (crypto === 'api') {
|
} else if (crypto === 'api') {
|
||||||
@@ -259,7 +259,7 @@ const createRequest = (uri, data, options) => {
|
|||||||
x.replace(/\s*Domain=[^(;|$)]+;*/, ''),
|
x.replace(/\s*Domain=[^(;|$)]+;*/, ''),
|
||||||
)
|
)
|
||||||
try {
|
try {
|
||||||
if (data.e_r) {
|
if (crypto === 'eapi' && data.e_r) {
|
||||||
// eapi接口返回值被加密,需要解密
|
// eapi接口返回值被加密,需要解密
|
||||||
answer.body = encrypt.eapiResDecrypt(
|
answer.body = encrypt.eapiResDecrypt(
|
||||||
body.toString('hex').toUpperCase(),
|
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