789 lines
23 KiB
Markdown
789 lines
23 KiB
Markdown
# 鎻掍欢寮€鍙戝府鍔╂枃妗?
|
||
> **鐗堟湰**: v1.0.3
|
||
>
|
||
> 鎾板啓浜? 铚昏湏鐨勫ソ鏈嬪弸 : Miao-moe
|
||
> GitHub: [Miao-moe](https://github.com/Miao-moe)
|
||
|
||
## 鐩綍
|
||
1. [姒傝堪](#姒傝堪)
|
||
2. [鏍稿績璁捐鍘熷垯](#鏍稿績璁捐鍘熷垯)
|
||
3. [浠庡叾浠栧钩鍙拌縼绉绘寚鍗梋(#浠庡叾浠栧钩鍙拌縼绉绘寚鍗?
|
||
4. [鎻掍欢鍩烘湰缁撴瀯](#鎻掍欢鍩烘湰缁撴瀯)
|
||
5. [鏁版嵁鏍煎紡瑙勮寖](#鏁版嵁鏍煎紡瑙勮寖)
|
||
6. [绀轰緥浠g爜璇﹁В](#绀轰緥浠g爜璇﹁В)
|
||
7. [骞冲彴閰嶇疆鍙傝€僝(#骞冲彴閰嶇疆鍙傝€?
|
||
8. [寮€鍙戝缓璁甝(#寮€鍙戝缓璁?
|
||
9. [甯歌闂](#甯歌闂)
|
||
|
||
---
|
||
|
||
## 姒傝堪
|
||
|
||
鏈枃妗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 env = global.env || {}
|
||
const API_KEY = env.API_KEY || ''
|
||
|
||
// 璇诲彇鑷畾涔夋湇鍔$鍦板潃
|
||
const CUSTOM_SERVER = 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 {
|
||
lrc: 'LRC鏍煎紡姝岃瘝',
|
||
qrc: 'QRC閫愬瓧姝岃瘝',
|
||
krc: 'KRC姝岃瘝',
|
||
ttml: 'TTML姝岃瘝',
|
||
translate: '缈昏瘧姝岃瘝'
|
||
}
|
||
|
||
// 鎴栫洿鎺ヨ繑鍥炴瓕璇嶆枃鏈瓧绗︿覆锛堢郴缁熶細鑷姩鍒ゆ柇鏍煎紡锛?return '[00:00.000]姝岃瘝鍐呭\n[00:05.000]绗簩琛屾瓕璇?..'
|
||
```
|
||
|
||
---
|
||
|
||
## 鎻掍欢鍩烘湰缁撴瀯
|
||
|
||
### 鏍稿績瀵煎叆
|
||
|
||
```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 // 骞冲彴鏍囪瘑
|
||
}
|
||
```
|
||
|
||
### 姝岃瘝杩斿洖鏍煎紡
|
||
|
||
**閲嶈璇存槑**锛氱郴缁熶細鑷姩鍒ゆ柇姝岃瘝鏍煎紡锛坙rc銆乹rc銆乲rc銆乼tml 绛夛級锛屾彃浠跺彧闇€杩斿洖瀵瑰簲鐨勬瓕璇嶅瓧娈靛嵆鍙€?
|
||
```javascript
|
||
// 鎺ㄨ崘杩斿洖鏍煎紡
|
||
{
|
||
lrc: String, // LRC 鏍煎紡姝岃瘝
|
||
qrc: String, // QRC 閫愬瓧姝岃瘝
|
||
krc: String, // KRC 姝岃瘝
|
||
ttml: String, // TTML 姝岃瘝
|
||
translate: String // 缈昏瘧姝岃瘝
|
||
}
|
||
|
||
// 鎴栬€呯洿鎺ヨ繑鍥炴瓕璇嶆枃鏈瓧绗︿覆锛堢郴缁熶細鑷姩鍒ゆ柇鏍煎紡锛?return '[00:00.000]姝岃瘝鍐呭\n[00:05.000]绗簩琛屾瓕璇?..'
|
||
```
|
||
|
||
**瀛楁璇存槑**锛?
|
||
| 瀛楁 | 璇存槑 | 鏍煎紡 |
|
||
|------|------|------|
|
||
| `lrc` | 鏍囧噯 LRC 姝岃瘝 | `[mm:ss.ms]姝岃瘝鍐呭` |
|
||
| `qrc` | 閫愬瓧姝岃瘝 | QRC 鏍煎紡锛圔ase64 缂栫爜锛?|
|
||
| `krc` | KRC 姝岃瘝 | KRC 鏍煎紡 |
|
||
| `ttml` | TTML 姝岃瘝 | TTML/XML 鏍煎紡 |
|
||
| `translate` | 缈昏瘧姝岃瘝 | LRC 鏍煎紡鎴栫函鏂囨湰 |
|
||
|
||
**娉ㄦ剰浜嬮」**锛?- 浠ヤ笂瀛楁鍧囦负鍙€夛紝杩斿洖鏈夌殑鍗冲彲
|
||
- 绯荤粺浼氳嚜鍔ㄨ瘑鍒瓕璇嶆牸寮?- `translate` 鐢ㄤ簬缈昏瘧姝岃瘝
|
||
- 鐩存帴杩斿洖姝岃瘝鏂囨湰瀛楃涓蹭篃鏄厑璁哥殑锛岀郴缁熶細灏濊瘯鑷姩鍒ゆ柇鍏舵牸寮?- 涓嶅悓骞冲彴鍙兘杩斿洖涓嶅悓鏍煎紡锛屽锛氬钩鍙癆鍙兘杩斿洖 `qrc` + `translate`锛屽钩鍙癇鍙兘杩斿洖 `lrc` + `tlyric`
|
||
|
||
### 鍒楄〃璇︽儏缁熶竴鏍煎紡
|
||
|
||
```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
|
||
'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']
|
||
|
||
// ==================== 宸ュ叿鍑芥暟 ====================
|
||
|
||
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'
|
||
}
|
||
|
||
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')
|
||
}
|
||
|
||
function formatArtistName(artistList) {
|
||
if (!artistList || !Array.isArray(artistList)) return ''
|
||
return artistList.map(a => a.name || a).join('銆?)
|
||
}
|
||
|
||
function decodeName(str) {
|
||
if (!str) return ''
|
||
return str
|
||
.replace(/'/g, "'")
|
||
.replace(/"/g, '"')
|
||
.replace(/</g, '<')
|
||
.replace(/>/g, '>')
|
||
.replace(/&/g, '&')
|
||
.replace(/ /g, ' ')
|
||
}
|
||
|
||
// ==================== 鏍稿績鍔熻兘 ====================
|
||
|
||
async function musicSearch(str, page = 1, limit = 20) {
|
||
const params = { keyword: str, page, limit }
|
||
|
||
const url = CONFIG.serverUrl + '/search'
|
||
const response = await axios.get(url, {
|
||
params,
|
||
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: {
|
||
'128k': sizeFormate(item.size128),
|
||
'320k': sizeFormate(item.size320),
|
||
'flac': sizeFormate(item.sizeFlac)
|
||
}
|
||
}))
|
||
|
||
return {
|
||
list,
|
||
total: data.total,
|
||
page,
|
||
limit,
|
||
allPage: Math.ceil(data.total / limit),
|
||
source: PLATFORM
|
||
}
|
||
}
|
||
|
||
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, 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
|
||
}
|
||
|
||
async function getLyric(id) {
|
||
const url = CONFIG.serverUrl + '/lyric'
|
||
const response = await axios.get(url, {
|
||
params: { id },
|
||
headers: { 'X-API-Key': CONFIG.apiKey },
|
||
timeout: CONFIG.timeout
|
||
})
|
||
|
||
const data = response.data
|
||
|
||
// 杩斿洖姝岃瘝瀵硅薄锛岀郴缁熶細鑷姩鍒ゆ柇鏍煎紡
|
||
// 杩斿洖鏈夌殑瀛楁鍗冲彲锛屼笉闇€瑕佸叏閮ㄥ瓧娈? return {
|
||
lrc: data.lrc || '',
|
||
qrc: data.qrc || '',
|
||
krc: data.krc || '',
|
||
ttml: data.ttml || '',
|
||
translate: data.translate || ''
|
||
}
|
||
|
||
// 鎴栬€呯洿鎺ヨ繑鍥炴瓕璇嶆枃鏈? // return data.lyric
|
||
}
|
||
|
||
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 || ''
|
||
}
|
||
}
|
||
}
|
||
|
||
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 || ''
|
||
}
|
||
}
|
||
}
|
||
|
||
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']
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 寮€鍙戝缓璁?
|
||
### 澶氭枃浠跺紑鍙?
|
||
**鎺ㄨ崘浣跨敤澶氭枃浠跺紑鍙戞ā寮?*锛屽皢涓嶅悓鍔熻兘妯″潡鍒嗙锛岄槻姝唬鐮佸爢鍙狅細
|
||
|
||
```
|
||
plugin/
|
||
鈹溾攢鈹€ index.js # 涓诲叆鍙o紝瀵煎嚭妯″潡
|
||
鈹溾攢鈹€ search.js # 鎼滅储鐩稿叧鍔熻兘
|
||
鈹溾攢鈹€ lyric.js # 姝岃瘝鐩稿叧鍔熻兘
|
||
鈹溾攢鈹€ playlist.js # 鍒楄〃鐩稿叧鍔熻兘
|
||
鈹溾攢鈹€ utils.js # 宸ュ叿鍑芥暟
|
||
鈹斺攢鈹€ config.js # 閰嶇疆甯搁噺
|
||
```
|
||
|
||
### 浣跨敤 ncc 鎵撳寘
|
||
|
||
寮€鍙戝畬鎴愬悗锛屼娇鐢?`ncc` 灏嗗鏂囦欢鎵撳寘涓哄崟鏂囦欢鍗冲彲锛?
|
||
```bash
|
||
# 瀹夎 ncc
|
||
npm install -g @vercel/ncc
|
||
|
||
# 鎵撳寘
|
||
ncc build index.js -o dist
|
||
|
||
# 杈撳嚭鐨?dist/index.js 鍗充负鏈€缁堟彃浠舵枃浠?```
|
||
|
||
**ncc 鎵撳寘浼樼偣**锛?- 灏嗗鏂囦欢鍚堝苟涓哄崟鏂囦欢锛屼究浜庡垎鍙?- 鑷姩澶勭悊渚濊禆鍏崇郴
|
||
- 淇濇寔 CommonJS 鍏煎鎬?
|
||
---
|
||
|
||
## 甯歌闂
|
||
|
||
### 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 || '榛樿鍦板潃'
|
||
```
|
||
|
||
### Q6: 姝岃瘝鏍煎紡搴旇杩斿洖浠€涔堬紵
|
||
|
||
**A**: 杩斿洖鍖呭惈 `lrc`銆乣qrc`銆乣krc`銆乣ttml`銆乣translate` 绛夊瓧娈电殑瀵硅薄锛屾垨鐩存帴杩斿洖姝岃瘝鏂囨湰瀛楃涓层€傜郴缁熶細鑷姩鍒ゆ柇姝岃瘝鏍煎紡銆?
|
||
---
|
||
|
||
## 闄勫綍
|
||
|
||
### 鍙傝€冭祫婧?
|
||
- Node.js 瀹樻柟鏂囨。
|
||
- axios 鏂囨。
|
||
- @vercel/ncc 鎵撳寘宸ュ叿
|
||
|
||
### 鐗堟湰鍘嗗彶
|
||
|
||
- v1.0.3: 褰撳墠鐗堟湰
|
||
- v1.0.0: 鍒濆鐗堟湰
|
||
|
||
---
|
||
|
||
**鏂囨。缁撴潫**
|