801 lines
22 KiB
Markdown
801 lines
22 KiB
Markdown
# 鎻掍欢寮€鍙戝府鍔╂枃妗?
|
||
## 鐩綍
|
||
1. [姒傝堪](#姒傝堪)
|
||
2. [鏍稿績璁捐鍘熷垯](#鏍稿績璁捐鍘熷垯)
|
||
3. [浠庡叾浠栧钩鍙拌縼绉绘寚鍗梋(#浠庡叾浠栧钩鍙拌縼绉绘寚鍗?
|
||
4. [鎻掍欢鍩烘湰缁撴瀯](#鎻掍欢鍩烘湰缁撴瀯)
|
||
5. [鏁版嵁鏍煎紡瑙勮寖](#鏁版嵁鏍煎紡瑙勮寖)
|
||
6. [绀轰緥浠g爜璇﹁В](#绀轰緥浠g爜璇﹁В)
|
||
7. [骞冲彴閰嶇疆鍙傝€僝(#骞冲彴閰嶇疆鍙傝€?
|
||
8. [甯歌闂](#甯歌闂)
|
||
|
||
---
|
||
|
||
## 姒傝堪
|
||
|
||
鏈枃妗g敤浜庢寚瀵煎紑鍙戣€呯紪鍐欓煶婧愭彃浠躲€傛湰绯荤粺浣跨敤 Node.js 杩愯鏃剁幆澧冿紝鎻掍欢閲囩敤 CommonJS 妯″潡瑙勮寖锛岄€氳繃 `module.exports` 瀵煎嚭鍔熻兘鎺ュ彛銆?
|
||
### 涓庡叾浠栫郴缁熺殑鍖哄埆
|
||
|
||
| 鐗规€?| 鏈郴缁?| 鍏朵粬绯荤粺 |
|
||
|------|--------|----------|
|
||
| 杩愯鏃?| Node.js | JavaScript 杩愯鏃?|
|
||
| 妯″潡瑙勮寖 | CommonJS | 鍏ㄥ眬浜嬩欢鐩戝惉 |
|
||
| 瀵煎嚭鏂瑰紡 | `module.exports` | 浜嬩欢鍙戦€?|
|
||
| 閫氫俊鏂瑰紡 | 鐩存帴鍑芥暟璋冪敤 | 浜嬩欢椹卞姩 |
|
||
| HTTP 璇锋眰 | `axios` 鎴栧唴缃?`httpFetch` | 鍏ㄥ眬璇锋眰瀵硅薄 |
|
||
|
||
### 鎻掍欢绫诲瀷
|
||
|
||
鏈郴缁熸彃浠跺睘浜?*瀹屾暣闊虫簮鎻掍欢**锛屾牳蹇冨姛鑳藉寘鎷細
|
||
- 鎼滅储鍐呭
|
||
- 鑾峰彇鎾斁 URL
|
||
- 鑾峰彇姝岃瘝
|
||
- 鑾峰彇鍒楄〃/鍚堥泦淇℃伅
|
||
- 鑾峰彇鐑悳/鎺掕姒?
|
||
---
|
||
|
||
## 鏍稿績璁捐鍘熷垯
|
||
|
||
### 1. 鍗曞钩鍙板師鍒欙紙閲嶈锛?
|
||
**姣忎釜鎻掍欢鍙敮鎸佷竴涓钩鍙?*锛屼緥濡傦細
|
||
- 鉁?骞冲彴A鎻掍欢锛堜粎鏀寔 A锛?- 鉁?骞冲彴B鎻掍欢锛堜粎鏀寔 B锛?- 鉂?鑱氬悎鎻掍欢锛堝悓鏃舵敮鎸?A + B + C锛?
|
||
**鍘熷洜璇存槑**锛?```
|
||
鐢ㄦ埛鍚戞彃浠朵紶閰嶇疆鍙兘閫氳繃鐜鍙橀噺锛坋nv锛?濡傛灉鎻掍欢鏀寔澶氬钩鍙帮紝鍒囨崲骞冲彴鏃堕渶瑕佷慨鏀圭幆澧冨彉閲忥紝鎿嶄綔绻佺悙
|
||
鍗曞钩鍙版彃浠舵洿娓呮櫚锛岀淮鎶ゆ垚鏈綆锛屼笉鏄撳嚭鐜?浠g爜灞庡北"
|
||
```
|
||
|
||
**濡傞渶澶氬钩鍙版敮鎸?*锛氬缓璁嚜寤哄悗绔湇鍔★紝缁熶竴澶勭悊鎼滅储鍜?URL 鑾峰彇锛屽墠绔彃浠跺彧浣滀负浠g悊銆?
|
||
### 2. 閰嶇疆鏂瑰紡
|
||
|
||
閫氳繃 `global.env` 璇诲彇鐜鍙橀噺锛圝SON 鏍煎紡锛夛細
|
||
|
||
```javascript
|
||
// 璇诲彇鐢ㄦ埛閰嶇疆鐨?API 瀵嗛挜
|
||
const API_KEY = global.env.API_KEY || ''
|
||
|
||
// 璇诲彇鑷畾涔夋湇鍔$鍦板潃
|
||
const CUSTOM_SERVER = global.env.SERVER_URL || '榛樿鍦板潃'
|
||
```
|
||
|
||
**鐜鍙橀噺鍔犺浇鏂瑰紡**锛?```javascript
|
||
const plugin = require('./index.js')
|
||
global.env = $envCommand // 鐢辩郴缁熸敞鍏ワ紝鏍煎紡涓?JSON
|
||
|
||
// 鍦ㄦ彃浠朵唬鐮佷腑閫氳繃 global.env 璇诲彇
|
||
const env = global.env || {}
|
||
const API_KEY = env.API_KEY || ''
|
||
```
|
||
|
||
### 3. 鏀寔鐨勯煶璐ㄦ爣璇?
|
||
| 鏍囪瘑 | 璇存槑 |
|
||
|------|------|
|
||
| `128k` | 鏍囧噯闊宠川 |
|
||
| `320k` | 楂樺搧闊宠川 |
|
||
| `flac` | 鏃犳崯闊宠川 |
|
||
| `flac24bit` | 楂樿В鏋愬害鏃犳崯 |
|
||
| `hires` | 瓒呴珮瑙f瀽搴?|
|
||
|
||
---
|
||
|
||
## 浠庡叾浠栧钩鍙拌縼绉绘寚鍗?
|
||
### 杩佺Щ瀵圭収琛?
|
||
| 鍏朵粬绯荤粺 | 鏈郴缁?| 璇存槑 |
|
||
|----------|--------|------|
|
||
| `globalThis.lx` | `require` 妯″潡 | 涓嶅啀闇€瑕佸叏灞€瀵硅薄 |
|
||
| `globalThis.lx.request` | `axios` 鎴?`httpFetch` | 浣跨敤鏍囧噯 HTTP 搴?|
|
||
| `globalThis.lx.env` | `global.env` | 鐜鍙橀噺璇诲彇鏂瑰紡 |
|
||
| `on(EVENT_NAMES.request, ...)` | 鐩存帴瀵煎嚭鍑芥暟 | 鏀逛负鍑芥暟瀵煎嚭 |
|
||
| `send(EVENT_NAMES.inited, ...)` | `module.exports` | 鏀逛负妯″潡瀵煎嚭 |
|
||
| `musicInfo.songmid` | `musicInfo.id` | 瀛楁鍚嶅彲鑳戒笉鍚?|
|
||
| `info.type` | `quality` 鍙傛暟 | 闊宠川鍙傛暟浣嶇疆 |
|
||
|
||
### 杩佺Щ姝ラ
|
||
|
||
#### 姝ラ 1锛氫慨鏀规ā鍧楀鍏?
|
||
**鍏朵粬绯荤粺鍘熶唬鐮侊細**
|
||
```javascript
|
||
const { EVENT_NAMES, request, on, send, env, version } = globalThis.lx
|
||
```
|
||
|
||
**鏈郴缁熸柊浠g爜锛?*
|
||
```javascript
|
||
const axios = require('axios')
|
||
const crypto = require('crypto')
|
||
|
||
// 鐜鍙橀噺浠?global.env 璇诲彇
|
||
const env = global.env || {}
|
||
const API_KEY = env.API_KEY || ''
|
||
```
|
||
|
||
#### 姝ラ 2锛氫慨鏀?HTTP 璇锋眰
|
||
|
||
**鍏朵粬绯荤粺鍘熶唬鐮侊細**
|
||
```javascript
|
||
function httpRequest(url) {
|
||
return new Promise((resolve, reject) => {
|
||
request(url, { headers }, (err, resp) => {
|
||
if (err) return reject(err)
|
||
resolve(resp.body)
|
||
})
|
||
})
|
||
}
|
||
```
|
||
|
||
**鏈郴缁熸柊浠g爜锛?*
|
||
```javascript
|
||
async function httpRequest(url, options = {}) {
|
||
const response = await axios({
|
||
url,
|
||
method: options.method || 'GET',
|
||
headers: options.headers,
|
||
timeout: options.timeout || 10000
|
||
})
|
||
return response.data
|
||
}
|
||
```
|
||
|
||
#### 姝ラ 3锛氫慨鏀瑰嚱鏁板鍑?
|
||
**鍏朵粬绯荤粺鍘熶唬鐮侊細**
|
||
```javascript
|
||
// 浜嬩欢鐩戝惉鏂瑰紡
|
||
on(EVENT_NAMES.request, ({ action, source, info }) => {
|
||
switch (action) {
|
||
case 'musicUrl':
|
||
return getMusicUrl(info.musicInfo, info.type)
|
||
}
|
||
})
|
||
|
||
// 鍒濆鍖栦簨浠?send(EVENT_NAMES.inited, {
|
||
status: true,
|
||
sources: musicSource
|
||
})
|
||
```
|
||
|
||
**鏈郴缁熸柊浠g爜锛?*
|
||
```javascript
|
||
// 鐩存帴瀵煎嚭鍑芥暟
|
||
module.exports = {
|
||
// 鎼滅储鍔熻兘
|
||
musicSearch,
|
||
|
||
// 鑾峰彇 URL
|
||
getUrl,
|
||
|
||
// 鑾峰彇姝岃瘝
|
||
getLyric,
|
||
|
||
// 鑾峰彇鍒楄〃
|
||
songList,
|
||
|
||
// 鑾峰彇鍚堥泦
|
||
album,
|
||
|
||
// 鑾峰彇鐑悳
|
||
hotSearch,
|
||
|
||
// 鎻掍欢淇℃伅
|
||
pluginInfo: {
|
||
info: { id: 'A', name: '骞冲彴A', version: '3' },
|
||
quality: [...],
|
||
supportFunc: [...]
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 姝ラ 4锛氫慨鏀硅繑鍥炴暟鎹牸寮?
|
||
**鍏朵粬绯荤粺鍘熶唬鐮侊細**
|
||
```javascript
|
||
// 鐩存帴杩斿洖 URL 瀛楃涓?return 'https://example.com/audio.mp3'
|
||
|
||
// 鎴栬繑鍥炴瓕璇嶅璞?return {
|
||
lyric: '[00:00.000]姝岃瘝鍐呭',
|
||
tlyric: '[00:00.000]缈昏瘧姝岃瘝'
|
||
}
|
||
```
|
||
|
||
**鏈郴缁熸柊浠g爜锛?*
|
||
```javascript
|
||
// 鎼滅储杩斿洖缁熶竴鏍煎紡
|
||
return {
|
||
list: [{
|
||
id: '123456',
|
||
name: '鍐呭鍚?,
|
||
artists: '鍒涗綔鑰?,
|
||
source: 'A',
|
||
pic: '灏侀潰URL',
|
||
mPic: '涓皝闈RL',
|
||
sPic: '灏忓皝闈RL',
|
||
albumName: '鍚堥泦鍚?,
|
||
albumId: '鍚堥泦ID',
|
||
interval: '03:45',
|
||
qualities: { '128k': '4.2M', 'flac': '35M' }
|
||
}],
|
||
total: 100,
|
||
page: 1,
|
||
limit: 20,
|
||
allPage: 5,
|
||
source: 'A'
|
||
}
|
||
|
||
// 姝岃瘝杩斿洖鏍煎紡
|
||
return {
|
||
lyric: '姝岃瘝鍐呭',
|
||
tlyric: '缈昏瘧姝岃瘝'
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 鎻掍欢鍩烘湰缁撴瀯
|
||
|
||
### 鏂囦欢澶撮儴娉ㄩ噴
|
||
|
||
```javascript
|
||
/**
|
||
* @name 骞冲彴A闊虫簮
|
||
* @description 闊虫簮鎻掍欢
|
||
* @version 3.0.0
|
||
* @author 寮€鍙戣€? * @homepage https://github.com/your-repo
|
||
* @license MIT
|
||
*
|
||
* 鏀寔骞冲彴: 骞冲彴A
|
||
* 鏀寔闊宠川: 128k, 320k, flac
|
||
*/
|
||
```
|
||
|
||
### 鏍稿績瀵煎叆
|
||
|
||
```javascript
|
||
'use strict'
|
||
|
||
// 鏍囧噯 Node.js 妯″潡
|
||
const axios = require('axios')
|
||
const crypto = require('crypto')
|
||
```
|
||
|
||
### 閰嶇疆鍖哄煙
|
||
|
||
```javascript
|
||
// ========== 鐢ㄦ埛鍙厤缃尯鍩?==========
|
||
|
||
// 浠?global.env 璇诲彇鐜鍙橀噺锛圝SON 鏍煎紡锛?const env = global.env || {}
|
||
|
||
// 鏈嶅姟绔湴鍧€锛堢敤鎴峰彲閫氳繃鐜鍙橀噺瑕嗙洊锛?const API_BASE = env.SERVER_URL || 'https://your-server.com'
|
||
|
||
// API 瀵嗛挜锛堢敤鎴烽€氳繃鐜鍙橀噺璁剧疆锛?const API_KEY = env.API_KEY || ''
|
||
|
||
// 褰撳墠骞冲彴鏍囪瘑锛堝崟骞冲彴鎻掍欢鍥哄畾鍊硷級
|
||
const PLATFORM = 'A'
|
||
|
||
// 鏀寔鐨勯煶璐ㄥ垪琛?const SUPPORT_QUALITIES = ['128k', '320k', 'flac']
|
||
```
|
||
|
||
### 瀵煎嚭缁撴瀯
|
||
|
||
```javascript
|
||
// ========== 鎻掍欢瀵煎嚭 ==========
|
||
|
||
module.exports = {
|
||
// 鏍稿績鍔熻兘锛堝繀椤诲疄鐜帮級
|
||
musicSearch, // 鍐呭鎼滅储
|
||
getUrl, // 鑾峰彇 URL
|
||
|
||
// 鍙€夊姛鑳? getLyric, // 鑾峰彇姝岃瘝
|
||
songList, // 鍒楄〃璇︽儏
|
||
album, // 鍚堥泦璇︽儏
|
||
hotSearch, // 鐑悳璇? tipSearch, // 鎼滅储鎻愮ず
|
||
leaderboard, // 鎺掕姒?
|
||
// 鎻掍欢淇℃伅锛堝繀椤伙級
|
||
pluginInfo: {
|
||
info: {
|
||
id: 'A', // 骞冲彴鏍囪瘑
|
||
name: '骞冲彴A', // 鏄剧ず鍚嶇О
|
||
description: '骞冲彴A鎻掍欢', // 鎻忚堪
|
||
version: '3' // 鐗堟湰鍙? },
|
||
env: [ // 鐜鍙橀噺閰嶇疆
|
||
{ key: 'API_KEY', name: 'API瀵嗛挜', description: '鏈嶅姟绔疉PI瀵嗛挜' }
|
||
],
|
||
ext: [], // 鎵╁睍鍔熻兘
|
||
quality: [ // 鏀寔鐨勯煶璐? { name: '鏍囧噯闊宠川', ui: '鏍?, id: '128k' },
|
||
{ name: '楂樺搧闊宠川', ui: 'HQ', id: '320k' },
|
||
{ name: '鏃犳崯闊宠川', ui: 'SQ', id: 'flac' }
|
||
],
|
||
supportFunc: [ // 鏀寔鐨勫姛鑳? 'search_song',
|
||
'search_playlist',
|
||
'playlist',
|
||
'album',
|
||
'lyric'
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 鏁版嵁鏍煎紡瑙勮寖
|
||
|
||
### 鎼滅储缁撴灉缁熶竴鏍煎紡
|
||
|
||
```javascript
|
||
{
|
||
list: [
|
||
{
|
||
id: String, // 鍞竴鏍囪瘑
|
||
name: String, // 鍚嶇О
|
||
artists: String, // 鍒涗綔鑰咃紙鐢?"銆? 鍒嗛殧锛? source: String, // 骞冲彴鏍囪瘑
|
||
pic: String, // 澶у皝闈?URL
|
||
mPic: String, // 涓皝闈?URL
|
||
sPic: String, // 灏忓皝闈?URL
|
||
albumName: String, // 鍚堥泦鍚? albumId: String, // 鍚堥泦 ID
|
||
interval: String, // 鏃堕暱 "mm:ss"
|
||
qualities: { // 闊宠川 -> 鏂囦欢澶у皬
|
||
'128k': '4.2M',
|
||
'320k': '8.5M',
|
||
'flac': '35M'
|
||
}
|
||
}
|
||
],
|
||
total: Number, // 鎬绘暟閲? page: Number, // 褰撳墠椤电爜
|
||
limit: Number, // 姣忛〉鏁伴噺
|
||
allPage: Number, // 鎬婚〉鏁? source: String // 骞冲彴鏍囪瘑
|
||
}
|
||
```
|
||
|
||
### 姝岃瘝缁熶竴鏍煎紡
|
||
|
||
```javascript
|
||
{
|
||
lyric: String, // 鏅€氭瓕璇? tlyric: String, // 缈昏瘧姝岃瘝
|
||
qrc: String, // 閫愬瓧姝岃瘝
|
||
roma: String // 闊宠瘧姝岃瘝
|
||
}
|
||
|
||
// 娉ㄦ剰锛氳嚦灏戣繑鍥?lyric 鎴?qrc 涔嬩竴
|
||
```
|
||
|
||
### 鍒楄〃璇︽儏缁熶竴鏍煎紡
|
||
|
||
```javascript
|
||
{
|
||
list: [/* 鍐呭鍒楄〃锛屾牸寮忓悓鎼滅储缁撴灉 */],
|
||
page: Number,
|
||
limit: Number,
|
||
total: Number,
|
||
source: String,
|
||
info: {
|
||
name: String, // 鍒楄〃鍚? img: String, // 灏侀潰鍥? desc: String, // 鎻忚堪
|
||
author: String // 鍒涘缓鑰? }
|
||
}
|
||
```
|
||
|
||
### 鍚堥泦璇︽儏缁熶竴鏍煎紡
|
||
|
||
```javascript
|
||
{
|
||
list: [/* 鍐呭鍒楄〃锛屾牸寮忓悓鎼滅储缁撴灉 */],
|
||
page: Number,
|
||
limit: Number,
|
||
total: Number,
|
||
source: String,
|
||
info: {
|
||
name: String, // 鍚堥泦鍚? img: String, // 灏侀潰鍥? desc: String, // 鎻忚堪
|
||
author: String // 鍒涗綔鑰? }
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 绀轰緥浠g爜璇﹁В
|
||
|
||
### 瀹屾暣鎻掍欢妯℃澘
|
||
|
||
```javascript
|
||
/**
|
||
* @name 骞冲彴A闊虫簮
|
||
* @description 闊虫簮鎻掍欢绀轰緥
|
||
* @version 3.0.0
|
||
* @author 寮€鍙戣€? *
|
||
* 鏀寔骞冲彴: 骞冲彴A
|
||
* 鏀寔闊宠川: 128k, 320k, flac
|
||
*/
|
||
|
||
'use strict'
|
||
|
||
// ==================== 鏍稿績瀵煎叆 ====================
|
||
|
||
const axios = require('axios')
|
||
const crypto = require('crypto')
|
||
|
||
// ==================== 閰嶇疆鍖哄煙 ====================
|
||
|
||
// 浠?global.env 璇诲彇鐜鍙橀噺锛圝SON 鏍煎紡锛?const env = global.env || {}
|
||
|
||
// 骞冲彴鏍囪瘑锛堝浐瀹氬€硷紝鍗曞钩鍙版彃浠讹級
|
||
const PLATFORM = 'A'
|
||
|
||
// 鏈嶅姟绔厤缃?const CONFIG = {
|
||
serverUrl: env.SERVER_URL || 'https://api.example.com',
|
||
apiKey: env.API_KEY || '',
|
||
timeout: 10000
|
||
}
|
||
|
||
// 鏀寔鐨勯煶璐?const SUPPORT_QUALITIES = ['128k', '320k', 'flac']
|
||
|
||
// ==================== 宸ュ叿鍑芥暟 ====================
|
||
|
||
/**
|
||
* 鏂囦欢澶у皬鏍煎紡鍖? * @param {number} size - 瀛楄妭鏁? * @returns {string} 鏍煎紡鍖栧悗鐨勫瓧绗︿覆
|
||
*/
|
||
function sizeFormate(size) {
|
||
if (!size || isNaN(size)) return ''
|
||
if (size > 104857600) return (size / 104857600).toFixed(1) + 'MB'
|
||
if (size > 1048576) return (size / 1048576).toFixed(1) + 'MB'
|
||
if (size > 1024) return (size / 1024).toFixed(1) + 'KB'
|
||
return size + 'B'
|
||
}
|
||
|
||
/**
|
||
* 鎾斁鏃堕棿鏍煎紡鍖? * @param {number} time - 绉掓暟
|
||
* @returns {string} 鏍煎紡鍖栧悗鐨勫瓧绗︿覆
|
||
*/
|
||
function formatPlayTime(time) {
|
||
if (!time || isNaN(time)) return '--/--'
|
||
const m = Math.floor(time / 60)
|
||
const s = Math.floor(time % 60)
|
||
return m + ':' + s.toString().padStart(2, '0')
|
||
}
|
||
|
||
/**
|
||
* 鍒涗綔鑰呭悕绉版牸寮忓寲
|
||
* @param {Array} artistList - 鍒涗綔鑰呭垪琛? * @returns {string} 鐢?"銆? 杩炴帴鐨勫垱浣滆€呭悕
|
||
*/
|
||
function formatArtistName(artistList) {
|
||
if (!artistList || !Array.isArray(artistList)) return ''
|
||
return artistList.map(a => a.name || a).join('銆?)
|
||
}
|
||
|
||
/**
|
||
* HTML 瀹炰綋瑙g爜
|
||
* @param {string} str - 鍚?HTML 瀹炰綋鐨勫瓧绗︿覆
|
||
* @returns {string} 瑙g爜鍚庣殑瀛楃涓? */
|
||
function decodeName(str) {
|
||
if (!str) return ''
|
||
return str
|
||
.replace(/'/g, "'")
|
||
.replace(/"/g, '"')
|
||
.replace(/</g, '<')
|
||
.replace(/>/g, '>')
|
||
.replace(/&/g, '&')
|
||
.replace(/ /g, ' ')
|
||
}
|
||
|
||
// ==================== 鏍稿績鍔熻兘 ====================
|
||
|
||
/**
|
||
* 鎼滅储鍐呭
|
||
* @param {string} str - 鎼滅储鍏抽敭璇? * @param {number} page - 椤电爜锛屼粠 1 寮€濮? * @param {number} limit - 姣忛〉鏁伴噺
|
||
* @returns {Promise<Object>} 鎼滅储缁撴灉
|
||
*/
|
||
async function musicSearch(str, page = 1, limit = 20) {
|
||
// 鏋勯€犺姹傚弬鏁? const params = {
|
||
keyword: str,
|
||
page: page,
|
||
limit: limit
|
||
}
|
||
|
||
// 鍙戦€佽姹? const url = `${CONFIG.serverUrl}/search`
|
||
const response = await axios.get(url, {
|
||
params,
|
||
headers: { 'X-API-Key': CONFIG.apiKey },
|
||
timeout: CONFIG.timeout
|
||
})
|
||
|
||
// 瑙f瀽鏁版嵁
|
||
const data = response.data
|
||
|
||
// 杞崲涓虹粺涓€鏍煎紡
|
||
const list = data.items.map(item => ({
|
||
id: String(item.id),
|
||
name: decodeName(item.name),
|
||
artists: formatArtistName(item.artists),
|
||
source: PLATFORM,
|
||
pic: item.picUrl || '',
|
||
mPic: item.picUrl || '',
|
||
sPic: item.picUrl || '',
|
||
albumName: decodeName(item.album?.name || ''),
|
||
albumId: String(item.album?.id || ''),
|
||
interval: formatPlayTime(item.duration),
|
||
qualities: {
|
||
'128k': sizeFormate(item.size128),
|
||
'320k': sizeFormate(item.size320),
|
||
'flac': sizeFormate(item.sizeFlac)
|
||
}
|
||
}))
|
||
|
||
return {
|
||
list,
|
||
total: data.total,
|
||
page: page,
|
||
limit: limit,
|
||
allPage: Math.ceil(data.total / limit),
|
||
source: PLATFORM
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 鑾峰彇鎾斁 URL
|
||
* @param {string} id - 鍐呭 ID
|
||
* @param {string} quality - 闊宠川鏍囪瘑
|
||
* @returns {Promise<string>} 鎾斁 URL
|
||
*/
|
||
async function getUrl(id, quality) {
|
||
// 妫€鏌ラ煶璐? if (!SUPPORT_QUALITIES.includes(quality)) {
|
||
quality = SUPPORT_QUALITIES[0]
|
||
}
|
||
|
||
// 鍙戦€佽姹? const url = `${CONFIG.serverUrl}/url`
|
||
const response = await axios.get(url, {
|
||
params: { id: id, quality: quality },
|
||
headers: { 'X-API-Key': CONFIG.apiKey },
|
||
timeout: CONFIG.timeout
|
||
})
|
||
|
||
const data = response.data
|
||
|
||
if (!data.url || !data.url.startsWith('http')) {
|
||
throw new Error('鑾峰彇閾炬帴澶辫触')
|
||
}
|
||
|
||
return data.url
|
||
}
|
||
|
||
/**
|
||
* 鑾峰彇姝岃瘝
|
||
* @param {string} id - 鍐呭 ID
|
||
* @returns {Promise<Object>} 姝岃瘝瀵硅薄
|
||
*/
|
||
async function getLyric(id) {
|
||
const url = `${CONFIG.serverUrl}/lyric`
|
||
const response = await axios.get(url, {
|
||
params: { id: id },
|
||
headers: { 'X-API-Key': CONFIG.apiKey },
|
||
timeout: CONFIG.timeout
|
||
})
|
||
|
||
const data = response.data
|
||
|
||
return {
|
||
lyric: data.lyric || '',
|
||
tlyric: data.tlyric || ''
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 鑾峰彇鍒楄〃璇︽儏
|
||
* @param {string} id - 鍒楄〃 ID
|
||
* @param {number} page - 椤电爜
|
||
* @param {number} limit - 姣忛〉鏁伴噺
|
||
* @returns {Promise<Object>} 鍒楄〃璇︽儏
|
||
*/
|
||
async function songList(id, page = 1, limit = 20) {
|
||
const url = `${CONFIG.serverUrl}/list`
|
||
const response = await axios.get(url, {
|
||
params: { id, page, limit },
|
||
headers: { 'X-API-Key': CONFIG.apiKey },
|
||
timeout: CONFIG.timeout
|
||
})
|
||
|
||
const data = response.data
|
||
|
||
// 杞崲鍐呭鍒楄〃
|
||
const list = data.items.map(item => ({
|
||
id: String(item.id),
|
||
name: decodeName(item.name),
|
||
artists: formatArtistName(item.artists),
|
||
source: PLATFORM,
|
||
pic: item.picUrl || '',
|
||
mPic: item.picUrl || '',
|
||
sPic: item.picUrl || '',
|
||
albumName: decodeName(item.album?.name || ''),
|
||
albumId: String(item.album?.id || ''),
|
||
interval: formatPlayTime(item.duration),
|
||
qualities: {}
|
||
}))
|
||
|
||
return {
|
||
list,
|
||
page,
|
||
limit,
|
||
total: data.total,
|
||
source: PLATFORM,
|
||
info: {
|
||
name: data.name || '',
|
||
img: data.cover || '',
|
||
desc: data.description || '',
|
||
author: data.creator?.name || ''
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 鑾峰彇鍚堥泦璇︽儏
|
||
* @param {string} id - 鍚堥泦 ID
|
||
* @param {number} page - 椤电爜
|
||
* @returns {Promise<Object>} 鍚堥泦璇︽儏
|
||
*/
|
||
async function album(id, page = 1) {
|
||
const url = `${CONFIG.serverUrl}/album`
|
||
const response = await axios.get(url, {
|
||
params: { id, page },
|
||
headers: { 'X-API-Key': CONFIG.apiKey },
|
||
timeout: CONFIG.timeout
|
||
})
|
||
|
||
const data = response.data
|
||
|
||
// 杞崲鍐呭鍒楄〃
|
||
const list = data.items.map(item => ({
|
||
id: String(item.id),
|
||
name: decodeName(item.name),
|
||
artists: formatArtistName(item.artists),
|
||
source: PLATFORM,
|
||
pic: item.picUrl || data.cover || '',
|
||
mPic: item.picUrl || data.cover || '',
|
||
sPic: item.picUrl || data.cover || '',
|
||
albumName: decodeName(data.name || ''),
|
||
albumId: String(id),
|
||
interval: formatPlayTime(item.duration),
|
||
qualities: {}
|
||
}))
|
||
|
||
return {
|
||
list,
|
||
page,
|
||
limit: 1000,
|
||
total: data.total,
|
||
source: PLATFORM,
|
||
info: {
|
||
name: data.name || '',
|
||
img: data.cover || '',
|
||
desc: data.description || '',
|
||
author: data.artist?.name || ''
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 鑾峰彇鐑悳璇? * @returns {Promise<Object>} 鐑悳鍒楄〃
|
||
*/
|
||
async function hotSearch() {
|
||
const url = `${CONFIG.serverUrl}/hotsearch`
|
||
const response = await axios.get(url, {
|
||
headers: { 'X-API-Key': CONFIG.apiKey },
|
||
timeout: CONFIG.timeout
|
||
})
|
||
|
||
return {
|
||
source: PLATFORM,
|
||
list: response.data.list || []
|
||
}
|
||
}
|
||
|
||
// ==================== 鎻掍欢瀵煎嚭 ====================
|
||
|
||
module.exports = {
|
||
// 鏍稿績鍔熻兘
|
||
musicSearch,
|
||
getUrl,
|
||
getLyric,
|
||
songList,
|
||
album,
|
||
hotSearch,
|
||
|
||
// 鎻掍欢淇℃伅
|
||
pluginInfo: {
|
||
info: {
|
||
id: PLATFORM,
|
||
name: '骞冲彴A',
|
||
description: '骞冲彴A鎻掍欢',
|
||
version: '3'
|
||
},
|
||
env: [
|
||
{ key: 'SERVER_URL', name: '鏈嶅姟绔湴鍧€', description: '鑷畾涔夋湇鍔$鍦板潃' },
|
||
{ key: 'API_KEY', name: 'API瀵嗛挜', description: '鏈嶅姟绔疉PI瀵嗛挜' }
|
||
],
|
||
ext: [],
|
||
quality: [
|
||
{ name: '鏍囧噯闊宠川', ui: '鏍?, id: '128k' },
|
||
{ name: '楂樺搧闊宠川', ui: 'HQ', id: '320k' },
|
||
{ name: '鏃犳崯闊宠川', ui: 'SQ', id: 'flac' }
|
||
],
|
||
supportFunc: ['search_song', 'search_playlist', 'playlist', 'album', 'lyric']
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 骞冲彴閰嶇疆鍙傝€?
|
||
### 鍚勫钩鍙版爣璇嗗鐓ц〃
|
||
|
||
| 骞冲彴 | 鏍囪瘑 | 甯歌 ID 瀛楁 |
|
||
|------|------|-------------|
|
||
| 骞冲彴A | `A` | `id` |
|
||
| 骞冲彴B | `B` | `id` |
|
||
| 骞冲彴C | `C` | `id`, `hash` |
|
||
| 骞冲彴D | `D` | `hash`, `id` |
|
||
| 骞冲彴E | `E` | `id` |
|
||
| 骞冲彴F | `F` | `id` |
|
||
|
||
### 闊宠川鏀寔鍙傝€?
|
||
```javascript
|
||
// 鍚勫钩鍙板父瑙侀煶璐ㄩ厤缃?const PLATFORM_QUALITIES = {
|
||
A: ['128k', '320k', 'flac', 'flac24bit', 'hires'],
|
||
B: ['128k', '320k', 'flac', 'flac24bit', 'hires'],
|
||
C: ['128k', '320k', 'flac', 'flac24bit'],
|
||
D: ['128k', '320k', 'flac', 'flac24bit', 'hires'],
|
||
E: ['128k', '320k', 'flac', 'flac24bit'],
|
||
F: ['128k', '320k', 'flac']
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 甯歌闂
|
||
|
||
### Q1: 濡備綍浠庡叾浠栫郴缁熻縼绉诲埌鏈郴缁燂紵
|
||
|
||
**A**: 鍙傝€冩湰鏂囨。鐨?浠庡叾浠栧钩鍙拌縼绉绘寚鍗?绔犺妭锛屼富瑕佷慨鏀圭偣锛?1. 灏?`globalThis.lx.request` 鏀逛负 `axios`
|
||
2. 灏嗕簨浠剁洃鍚敼涓哄嚱鏁板鍑?3. 淇敼鏁版嵁杩斿洖鏍煎紡
|
||
4. 娣诲姞 `module.exports` 瀵煎嚭
|
||
5. 鐜鍙橀噺浠?`global.env` 璇诲彇
|
||
|
||
### Q2: 鎻掍欢鍔犺浇澶辫触鎬庝箞鍔烇紵
|
||
|
||
**A**: 妫€鏌ヤ互涓嬪嚑鐐癸細
|
||
1. 鏂囦欢璇硶鏄惁姝g‘锛歚node -c your-plugin.js`
|
||
2. `pluginInfo` 鏄惁瀹屾暣
|
||
3. 瀵煎嚭鐨勫嚱鏁板悕鏄惁姝g‘
|
||
4. 渚濊禆妯″潡鏄惁宸插畨瑁咃紙濡?`axios`锛?
|
||
### Q3: 鎼滅储杩斿洖绌虹粨鏋滐紵
|
||
|
||
**A**: 妫€鏌ワ細
|
||
1. API 璇锋眰鏄惁鎴愬姛锛堟煡鐪嬫棩蹇楋級
|
||
2. 鍝嶅簲鏁版嵁瑙f瀽鏄惁姝g‘
|
||
3. 鏁版嵁鏍煎紡鏄惁绗﹀悎瑙勮寖
|
||
4. 杩斿洖鐨?`source` 鏄惁涓庡钩鍙版爣璇嗕竴鑷?
|
||
### Q4: 鎾斁澶辫触锛?
|
||
**A**: 妫€鏌ワ細
|
||
1. `getUrl` 杩斿洖鐨?URL 鏄惁鏈夋晥
|
||
2. URL 鏄惁浠?`http` 寮€澶?3. 闊宠川鏍囪瘑鏄惁姝g‘
|
||
4. 鏄惁鏈夎法鍩熸垨鏉冮檺闂
|
||
|
||
### Q5: 鐢ㄦ埛濡備綍閰嶇疆鎻掍欢锛?
|
||
**A**: 鐢ㄦ埛閫氳繃璁剧疆鐣岄潰閰嶇疆鐜鍙橀噺锛?
|
||
```
|
||
SERVER_URL = 鑷畾涔夋湇鍔$鍦板潃
|
||
API_KEY = 鐢ㄦ埛鐨凙PI瀵嗛挜
|
||
```
|
||
|
||
鎻掍欢閫氳繃 `global.env` 璇诲彇锛?
|
||
```javascript
|
||
const env = global.env || {}
|
||
const SERVER_URL = env.SERVER_URL || '榛樿鍦板潃'
|
||
```
|
||
|
||
---
|
||
|
||
## 闄勫綍
|
||
|
||
### 鍙傝€冭祫婧?
|
||
- Node.js 瀹樻柟鏂囨。
|
||
- axios 鏂囨。
|
||
|
||
### 鐗堟湰鍘嗗彶
|
||
|
||
- v1.0.0 (2024-05-28): 鍒濆鐗堟湰
|
||
|
||
---
|
||
|
||
**鏂囨。缁撴潫**
|