@zhin.js/plugin-music 1.0.25 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +1 -0
  2. package/commands/cookie/delete/[source].js +23 -0
  3. package/commands/cookie/delete/[source].ts +27 -0
  4. package/commands/cookie/get/[source].js +29 -0
  5. package/commands/cookie/get/[source].ts +33 -0
  6. package/commands/cookie/set/[source].js +23 -0
  7. package/commands/cookie/set/[source].ts +27 -0
  8. package/commands/cookie/status.js +25 -0
  9. package/commands/cookie/status.ts +25 -0
  10. package/commands/login/[platform].js +64 -0
  11. package/commands/login/[platform].ts +76 -0
  12. package/commands//347/202/271/346/255/214/[keyword].js +62 -0
  13. package/commands//347/202/271/346/255/214/[keyword].ts +74 -0
  14. package/components/share-music.js +24 -0
  15. package/components/share-music.ts +29 -0
  16. package/lib/config.d.ts +3 -3
  17. package/lib/config.d.ts.map +1 -1
  18. package/lib/config.js +36 -7
  19. package/lib/config.js.map +1 -1
  20. package/lib/credential-store.d.ts +34 -0
  21. package/lib/credential-store.d.ts.map +1 -0
  22. package/lib/credential-store.js +111 -0
  23. package/lib/credential-store.js.map +1 -0
  24. package/lib/index.d.ts +7 -1
  25. package/lib/index.d.ts.map +1 -1
  26. package/lib/index.js +6 -112
  27. package/lib/index.js.map +1 -1
  28. package/lib/login/index.d.ts +20 -0
  29. package/lib/login/index.d.ts.map +1 -0
  30. package/lib/login/index.js +100 -0
  31. package/lib/login/index.js.map +1 -0
  32. package/lib/login/netease.d.ts +6 -0
  33. package/lib/login/netease.d.ts.map +1 -0
  34. package/lib/login/netease.js +58 -0
  35. package/lib/login/netease.js.map +1 -0
  36. package/lib/login/qq.d.ts +7 -0
  37. package/lib/login/qq.d.ts.map +1 -0
  38. package/lib/login/qq.js +139 -0
  39. package/lib/login/qq.js.map +1 -0
  40. package/lib/login/types.d.ts +19 -0
  41. package/lib/login/types.d.ts.map +1 -0
  42. package/lib/login/types.js +11 -0
  43. package/lib/login/types.js.map +1 -0
  44. package/lib/music-lib.d.ts +31 -0
  45. package/lib/music-lib.d.ts.map +1 -0
  46. package/lib/music-lib.js +59 -0
  47. package/lib/music-lib.js.map +1 -0
  48. package/lib/session.d.ts +29 -0
  49. package/lib/session.d.ts.map +1 -0
  50. package/lib/session.js +39 -0
  51. package/lib/session.js.map +1 -0
  52. package/lib/sources/index.d.ts +2 -1
  53. package/lib/sources/index.d.ts.map +1 -1
  54. package/lib/sources/index.js +6 -2
  55. package/lib/sources/index.js.map +1 -1
  56. package/lib/sources/kugou.d.ts +6 -0
  57. package/lib/sources/kugou.d.ts.map +1 -0
  58. package/lib/sources/kugou.js +54 -0
  59. package/lib/sources/kugou.js.map +1 -0
  60. package/lib/sources/kuwo.d.ts +7 -0
  61. package/lib/sources/kuwo.d.ts.map +1 -0
  62. package/lib/sources/kuwo.js +69 -0
  63. package/lib/sources/kuwo.js.map +1 -0
  64. package/lib/sources/netease.d.ts +1 -1
  65. package/lib/sources/netease.d.ts.map +1 -1
  66. package/lib/sources/netease.js +22 -6
  67. package/lib/sources/netease.js.map +1 -1
  68. package/lib/sources/qq.d.ts +1 -14
  69. package/lib/sources/qq.d.ts.map +1 -1
  70. package/lib/sources/qq.js +114 -82
  71. package/lib/sources/qq.js.map +1 -1
  72. package/lib/types.d.ts +4 -24
  73. package/lib/types.d.ts.map +1 -1
  74. package/lib/types.js +0 -1
  75. package/lib/types.js.map +1 -1
  76. package/middlewares/music-selection.js +46 -0
  77. package/middlewares/music-selection.ts +56 -0
  78. package/package.json +62 -13
  79. package/plugin.js +31 -0
  80. package/schema.json +6 -0
  81. package/src/config.ts +54 -30
  82. package/src/credential-store.ts +169 -0
  83. package/src/index.ts +45 -0
  84. package/src/login/index.ts +135 -0
  85. package/src/login/netease.ts +69 -0
  86. package/src/login/qq.ts +154 -0
  87. package/src/login/types.ts +27 -0
  88. package/src/music-lib.ts +70 -0
  89. package/src/session.ts +60 -0
  90. package/src/sources/index.ts +12 -8
  91. package/src/sources/kugou.ts +78 -0
  92. package/src/sources/kuwo.ts +94 -0
  93. package/src/sources/netease.ts +29 -11
  94. package/src/sources/qq.ts +158 -126
  95. package/src/types.ts +6 -28
  96. package/tools/music-search.js +21 -0
  97. package/tools/music-search.ts +27 -0
  98. package/tools/music-share.js +20 -0
  99. package/tools/music-share.ts +24 -0
  100. package/lib/async-jsx.d.ts +0 -19
  101. package/lib/async-jsx.d.ts.map +0 -1
  102. package/lib/async-jsx.js +0 -48
  103. package/lib/async-jsx.js.map +0 -1
  104. package/src/async-jsx.ts +0 -54
  105. package/src/index.tsx +0 -130
  106. /package/{skills/music/SKILL.md → agent/skills/music.md} +0 -0
@@ -1,3 +1,4 @@
1
+ import { getCredential } from '../credential-store.js';
1
2
  /** 网易云音乐搜索服务 */
2
3
  export class NeteaseMusicService {
3
4
  async search(keyword, limit = 10) {
@@ -60,16 +61,31 @@ export class NeteaseMusicService {
60
61
  * @param metingAPI Meting API 地址(可选)
61
62
  * @returns 音频直链 URL
62
63
  */
63
- async getAudioUrl(id, metingAPI) {
64
- // 默认使用 Meting API
65
- const apiUrl = metingAPI || 'https://api.injahow.cn/meting/';
64
+ async getAudioUrl(id) {
65
+ const cookie = await getCredential('netease', 'cookie');
66
+ if (cookie) {
67
+ try {
68
+ const response = await fetch(`https://music.163.com/api/song/enhance/player/url?ids=[${id}]&br=320000`, {
69
+ method: 'GET',
70
+ headers: { Cookie: cookie },
71
+ });
72
+ const result = await response.json();
73
+ const audioUrl = result.data?.[0]?.url;
74
+ if (audioUrl)
75
+ return audioUrl;
76
+ }
77
+ catch {
78
+ // cookie-based fetch failed, fall through to public API
79
+ }
80
+ }
81
+ const apiUrl = 'https://api.injahow.cn/meting/';
66
82
  const url = `${apiUrl}?type=url&id=${id}`;
67
83
  const response = await fetch(url, { method: 'GET' });
68
84
  const data = await response.json();
69
- if (!data.url && !data.data?.url)
85
+ const audioUrl = data.url ?? data.data?.url;
86
+ if (!audioUrl)
70
87
  throw new Error('Audio URL not found');
71
- // 不同的 Meting API 返回格式可能不同
72
- return data.url || data.data?.url;
88
+ return audioUrl;
73
89
  }
74
90
  }
75
91
  //# sourceMappingURL=netease.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"netease.js","sourceRoot":"","sources":["../../src/sources/netease.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"netease.js","sourceRoot":"","sources":["../../src/sources/netease.ts"],"names":[],"mappings":"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"}
@@ -1,21 +1,8 @@
1
1
  import type { MusicSearchService, MusicDetail, MusicInfo } from '../types.js';
2
- /** QQ 音乐搜索服务 */
3
2
  export declare class QQMusicService implements MusicSearchService {
4
3
  search(keyword: string, limit?: number): Promise<MusicInfo[]>;
5
- getCover(id: string): Promise<string | null>;
6
4
  getDetail(id: string): Promise<MusicDetail>;
7
- /**
8
- * 获取音频直链(需要第三方 API)
9
- * @param id 音乐 ID
10
- * @param metingAPI Meting API 地址(可选)
11
- * @returns 音频直链 URL
12
- */
13
- getAudioUrl(id: string, metingAPI?: string): Promise<string>;
14
- /**
15
- * 获取歌词
16
- * @param id 音乐 ID
17
- * @returns 歌词文本
18
- */
5
+ getAudioUrl(id: string, mid?: string, mediaMid?: string): Promise<string>;
19
6
  getLyric(id: string): Promise<string | null>;
20
7
  }
21
8
  //# sourceMappingURL=qq.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"qq.d.ts","sourceRoot":"","sources":["../../src/sources/qq.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAC,SAAS,EAAW,MAAM,aAAa,CAAA;AAErF,gBAAgB;AAChB,qBAAa,cAAe,YAAW,kBAAkB;IACjD,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAsBzD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA+B5C,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAkCjD;;;;;OAKG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAalE;;;;OAIG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CA+BnD"}
1
+ {"version":3,"file":"qq.d.ts","sourceRoot":"","sources":["../../src/sources/qq.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAe9E,qBAAa,cAAe,YAAW,kBAAkB;IACjD,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IA0DzD,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAkC3C,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiDzE,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAqBnD"}
package/lib/sources/qq.js CHANGED
@@ -1,64 +1,80 @@
1
- /** QQ 音乐搜索服务 */
1
+ import * as crypto from 'node:crypto';
2
+ import { getCredential } from '../credential-store.js';
3
+ const md5 = (text) => crypto.createHash('md5').update(text).digest('hex');
4
+ const MUSICU_API = 'https://u.y.qq.com/cgi-bin/musicu.fcg';
5
+ function getHeaders(cookie) {
6
+ return {
7
+ Referer: 'https://y.qq.com',
8
+ Cookie: cookie ?? '',
9
+ 'Content-Type': 'application/json; charset=UTF-8',
10
+ };
11
+ }
2
12
  export class QQMusicService {
3
13
  async search(keyword, limit = 10) {
4
14
  try {
5
- const url = new URL('https://c.y.qq.com/splcloud/fcgi-bin/smartbox_new.fcg');
6
- url.searchParams.set('key', keyword);
7
- url.searchParams.set('format', 'json');
8
- const response = await fetch(url, { method: 'GET' });
9
- const data = await response.json();
10
- const items = data.data?.song?.itemlist || [];
11
- return items.slice(0, limit).map(music => ({
12
- id: music.id,
13
- source: 'qq',
14
- title: music.name,
15
- url: `https://y.qq.com/n/yqq/song/${music.mid}.html`
16
- }));
15
+ const cookie = await getCredential('qq', 'cookie');
16
+ const response = await fetch(MUSICU_API, {
17
+ method: 'POST',
18
+ headers: getHeaders(cookie),
19
+ body: JSON.stringify({
20
+ comm: { uin: '0', authst: '', ct: 29 },
21
+ search: {
22
+ method: 'DoSearchForQQMusicMobile',
23
+ module: 'music.search.SearchCgiService',
24
+ param: {
25
+ query: keyword,
26
+ grp: 1,
27
+ num_per_page: limit,
28
+ page_num: 1,
29
+ search_type: 0,
30
+ searchid: String(Date.now()),
31
+ },
32
+ },
33
+ }),
34
+ });
35
+ const data = (await response.json());
36
+ if (data.code !== undefined && +data.code !== 0)
37
+ return [];
38
+ const body = data.search?.data?.body ?? {};
39
+ const list = (body.song?.list ?? body.item_song ?? []);
40
+ return list.slice(0, limit).map((e) => {
41
+ const mid = e?.mid ?? '';
42
+ const albumMid = e?.album?.pmid ?? e?.album?.mid ?? '';
43
+ const singerMid = e?.singer?.[0]?.pmid ?? e?.singer?.[0]?.mid ?? '';
44
+ const cover = albumMid
45
+ ? `https://y.gtimg.cn/music/photo_new/T002R300x300M000${albumMid}.jpg`
46
+ : singerMid
47
+ ? `https://y.qq.com/music/photo_new/T001R300x300M000${singerMid}.jpg`
48
+ : '';
49
+ return {
50
+ id: String(e.id),
51
+ source: 'qq',
52
+ title: e.name,
53
+ artist: (e.singer ?? []).map((s) => s.name).join('/'),
54
+ album: e.album?.name,
55
+ url: `https://y.qq.com/n/ryqq/songDetail/${mid}`,
56
+ image: cover,
57
+ duration: e.interval,
58
+ _mid: mid,
59
+ _mediaMid: e.file?.media_mid,
60
+ };
61
+ });
17
62
  }
18
63
  catch (error) {
19
64
  console.error('QQ Music search failed:', error);
20
65
  return [];
21
66
  }
22
67
  }
23
- async getCover(id) {
24
- try {
25
- const url = new URL('https://u.y.qq.com/cgi-bin/musicu.fcg');
26
- url.searchParams.set('format', 'json');
27
- url.searchParams.set('inCharset', 'utf8');
28
- url.searchParams.set('outCharset', 'utf-8');
29
- url.searchParams.set('notice', '0');
30
- url.searchParams.set('platform', 'yqq.json');
31
- url.searchParams.set('needNewCode', '0');
32
- url.searchParams.set('data', JSON.stringify({
33
- comm: { ct: 24, cv: 0 },
34
- songinfo: {
35
- method: 'get_song_detail_yqq',
36
- param: { song_type: 0, song_mid: '', song_id: parseInt(id) },
37
- module: 'music.pf_song_detail_svr'
38
- }
39
- }));
40
- const response = await fetch(url, { method: 'GET' });
41
- const result = await response.json();
42
- const albumMid = result?.songinfo?.data?.track_info?.album?.mid;
43
- if (!albumMid)
44
- return null;
45
- return `https://y.gtimg.cn/music/photo_new/T002R300x300M000${albumMid}.jpg`;
46
- }
47
- catch (error) {
48
- console.error('QQ Music get cover failed:', error);
49
- return null;
50
- }
51
- }
52
68
  async getDetail(id) {
53
- const url = new URL('https://u.y.qq.com/cgi-bin/musicu.fcg');
69
+ const url = new URL(MUSICU_API);
54
70
  url.searchParams.set('format', 'json');
55
71
  url.searchParams.set('data', JSON.stringify({
56
72
  comm: { ct: 24, cv: 0 },
57
73
  songinfo: {
58
74
  method: 'get_song_detail_yqq',
59
75
  param: { song_type: 0, song_mid: '', song_id: parseInt(id) },
60
- module: 'music.pf_song_detail_svr'
61
- }
76
+ module: 'music.pf_song_detail_svr',
77
+ },
62
78
  }));
63
79
  const response = await fetch(url, { method: 'GET' });
64
80
  const result = await response.json();
@@ -68,39 +84,65 @@ export class QQMusicService {
68
84
  const albumMid = trackInfo.album?.mid;
69
85
  const image = albumMid
70
86
  ? `https://y.gtimg.cn/music/photo_new/T002R300x300M000${albumMid}.jpg`
71
- : undefined;
87
+ : '';
72
88
  return {
73
89
  id,
74
90
  source: 'qq',
75
91
  title: trackInfo.name,
76
- url: `https://y.qq.com/n/yqq/song/${trackInfo.mid}.html`,
77
- audio: await this.getAudioUrl(id),
78
- image: image || '',
92
+ url: `https://y.qq.com/n/ryqq/songDetail/${trackInfo.mid}`,
93
+ audio: await this.getAudioUrl(id, trackInfo.mid, trackInfo.file?.media_mid),
94
+ image,
79
95
  duration: trackInfo.interval,
80
96
  };
81
97
  }
82
- /**
83
- * 获取音频直链(需要第三方 API)
84
- * @param id 音乐 ID
85
- * @param metingAPI Meting API 地址(可选)
86
- * @returns 音频直链 URL
87
- */
88
- async getAudioUrl(id, metingAPI) {
89
- // QQ 音乐需要使用第三方 API
90
- const apiUrl = metingAPI || 'https://api.injahow.cn/meting/';
91
- const url = `${apiUrl}?type=url&id=${id}&source=qq`;
92
- const response = await fetch(url, { method: 'GET' });
93
- const data = await response.json();
94
- if (!data.url && !data.data?.url) {
95
- throw new Error('Audio URL not found');
98
+ async getAudioUrl(id, mid, mediaMid) {
99
+ const cookie = await getCredential('qq', 'cookie');
100
+ if (cookie) {
101
+ try {
102
+ const uin = /uin=o?(\d+)/.exec(cookie)?.[1] ?? '0';
103
+ const songMid = mid ?? id;
104
+ const response = await fetch(MUSICU_API, {
105
+ method: 'POST',
106
+ headers: getHeaders(cookie),
107
+ body: JSON.stringify({
108
+ comm: {
109
+ ct: 19,
110
+ cv: '1891',
111
+ uin: '0',
112
+ guid: md5(`${uin}music`),
113
+ tmeAppID: 'qqmusic',
114
+ tmeLoginType: 2,
115
+ },
116
+ vkey: {
117
+ module: 'vkey.GetVkeyServer',
118
+ method: 'CgiGetVkey',
119
+ param: {
120
+ guid: md5(String(Date.now())),
121
+ songmid: [songMid],
122
+ songtype: [0],
123
+ uin: '0',
124
+ ctx: 1,
125
+ filename: [`C400${id}${mediaMid ?? songMid}.m4a`],
126
+ },
127
+ },
128
+ }),
129
+ });
130
+ const result = await response.json();
131
+ if (result.vkey && +result.vkey.code === 0) {
132
+ const purl = result.vkey.data?.midurlinfo?.[0]?.purl;
133
+ if (purl)
134
+ return `https://ws.stream.qqmusic.qq.com/${purl}`;
135
+ }
136
+ }
137
+ catch {
138
+ // fall through to public fallback
139
+ }
96
140
  }
97
- return data.url || data.data?.url;
141
+ // 无 cookie 的公开 fallback:md5 签名直链
142
+ const songMid = mid ?? id;
143
+ const code = md5(`${songMid}q;z(&l~sdf2!nK`).substring(0, 5).toUpperCase();
144
+ return `https://c6.y.qq.com/rsc/fcgi-bin/fcg_pyq_play.fcg?songmid=${songMid}&code=${code}`;
98
145
  }
99
- /**
100
- * 获取歌词
101
- * @param id 音乐 ID
102
- * @returns 歌词文本
103
- */
104
146
  async getLyric(id) {
105
147
  try {
106
148
  const url = new URL('https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg');
@@ -112,20 +154,10 @@ export class QQMusicService {
112
154
  url.searchParams.set('nobase64', '1');
113
155
  const response = await fetch(url, {
114
156
  method: 'GET',
115
- headers: {
116
- 'Referer': 'https://y.qq.com'
117
- }
157
+ headers: { Referer: 'https://y.qq.com' },
118
158
  });
119
- const data = await response.json();
120
- if (!data.lyric)
121
- return null;
122
- // QQ 音乐返回的歌词需要 base64 解码
123
- try {
124
- return Buffer.from(data.lyric, 'base64').toString('utf-8');
125
- }
126
- catch {
127
- return data.lyric;
128
- }
159
+ const data = (await response.json());
160
+ return data.lyric ?? null;
129
161
  }
130
162
  catch (error) {
131
163
  console.error('QQ Music get lyric failed:', error);
@@ -1 +1 @@
1
- {"version":3,"file":"qq.js","sourceRoot":"","sources":["../../src/sources/qq.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"qq.js","sourceRoot":"","sources":["../../src/sources/qq.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAElF,MAAM,UAAU,GAAG,uCAAuC,CAAC;AAE3D,SAAS,UAAU,CAAC,MAAsB;IACxC,OAAO;QACL,OAAO,EAAE,kBAAkB;QAC3B,MAAM,EAAE,MAAM,IAAI,EAAE;QACpB,cAAc,EAAE,iCAAiC;KAClD,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,cAAc;IACzB,KAAK,CAAC,MAAM,CAAC,OAAe,EAAE,KAAK,GAAG,EAAE;QACtC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACnD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE;gBACvC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC;gBAC3B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;oBACtC,MAAM,EAAE;wBACN,MAAM,EAAE,0BAA0B;wBAClC,MAAM,EAAE,+BAA+B;wBACvC,KAAK,EAAE;4BACL,KAAK,EAAE,OAAO;4BACd,GAAG,EAAE,CAAC;4BACN,YAAY,EAAE,KAAK;4BACnB,QAAQ,EAAE,CAAC;4BACX,WAAW,EAAE,CAAC;4BACd,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;yBAC7B;qBACF;iBACF,CAAC;aACH,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAqG,CAAC;YACzI,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YAE3D,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;YAC3C,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC,SAAS,IAAI,EAAE,CAAU,CAAC;YAEhE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACpC,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC;gBACzB,MAAM,QAAQ,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,CAAC;gBACvD,MAAM,SAAS,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC;gBACpE,MAAM,KAAK,GAAG,QAAQ;oBACpB,CAAC,CAAC,sDAAsD,QAAQ,MAAM;oBACtE,CAAC,CAAC,SAAS;wBACT,CAAC,CAAC,oDAAoD,SAAS,MAAM;wBACrE,CAAC,CAAC,EAAE,CAAC;gBAET,OAAO;oBACL,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;oBAChB,MAAM,EAAE,IAAa;oBACrB,KAAK,EAAE,CAAC,CAAC,IAAI;oBACb,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;oBAC1D,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI;oBACpB,GAAG,EAAE,sCAAsC,GAAG,EAAE;oBAChD,KAAK,EAAE,KAAK;oBACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;oBACpB,IAAI,EAAE,GAAG;oBACT,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS;iBAC7B,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAChD,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,EAAU;QACxB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;QAChC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACvC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;YAC1C,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE;YACvB,QAAQ,EAAE;gBACR,MAAM,EAAE,qBAAqB;gBAC7B,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE;gBAC5D,MAAM,EAAE,0BAA0B;aACnC;SACF,CAAC,CAAC,CAAC;QAEJ,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAS,CAAC;QAE5C,MAAM,SAAS,GAAG,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,CAAC;QACrD,IAAI,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAEnD,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC;QACtC,MAAM,KAAK,GAAG,QAAQ;YACpB,CAAC,CAAC,sDAAsD,QAAQ,MAAM;YACtE,CAAC,CAAC,EAAE,CAAC;QAEP,OAAO;YACL,EAAE;YACF,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,SAAS,CAAC,IAAI;YACrB,GAAG,EAAE,sCAAsC,SAAS,CAAC,GAAG,EAAE;YAC1D,KAAK,EAAE,MAAM,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC;YAC3E,KAAK;YACL,QAAQ,EAAE,SAAS,CAAC,QAAQ;SAC7B,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,EAAU,EAAE,GAAY,EAAE,QAAiB;QAC3D,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnD,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;gBACnD,MAAM,OAAO,GAAG,GAAG,IAAI,EAAE,CAAC;gBAC1B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE;oBACvC,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC;oBAC3B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACnB,IAAI,EAAE;4BACJ,EAAE,EAAE,EAAE;4BACN,EAAE,EAAE,MAAM;4BACV,GAAG,EAAE,GAAG;4BACR,IAAI,EAAE,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC;4BACxB,QAAQ,EAAE,SAAS;4BACnB,YAAY,EAAE,CAAC;yBAChB;wBACD,IAAI,EAAE;4BACJ,MAAM,EAAE,oBAAoB;4BAC5B,MAAM,EAAE,YAAY;4BACpB,KAAK,EAAE;gCACL,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;gCAC7B,OAAO,EAAE,CAAC,OAAO,CAAC;gCAClB,QAAQ,EAAE,CAAC,CAAC,CAAC;gCACb,GAAG,EAAE,GAAG;gCACR,GAAG,EAAE,CAAC;gCACN,QAAQ,EAAE,CAAC,OAAO,EAAE,GAAG,QAAQ,IAAI,OAAO,MAAM,CAAC;6BAClD;yBACF;qBACF,CAAC;iBACH,CAAC,CAAC;gBAEH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAS,CAAC;gBAC5C,IAAI,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;oBAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;oBACrD,IAAI,IAAI;wBAAE,OAAO,oCAAoC,IAAI,EAAE,CAAC;gBAC9D,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,kCAAkC;YACpC,CAAC;QACH,CAAC;QAED,iCAAiC;QACjC,MAAM,OAAO,GAAG,GAAG,IAAI,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,OAAO,gBAAgB,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC3E,OAAO,6DAA6D,OAAO,SAAS,IAAI,EAAE,CAAC;IAC7F,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,2DAA2D,CAAC,CAAC;YACjF,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YACpC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACrC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACvC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;YAC1C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YAC5C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;YAEtC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE;aACzC,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAuB,CAAC;YAC3D,OAAO,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
package/lib/types.d.ts CHANGED
@@ -1,20 +1,17 @@
1
- /** 音乐源类型 */
2
- export type MusicSource = "qq" | "netease";
3
- /** 音乐分享内容 */
1
+ export type MusicSource = 'qq' | 'netease' | 'kuwo' | 'kugou';
4
2
  export interface MusicInfo {
5
3
  id: string;
6
4
  source: MusicSource;
7
- /** 跳转链接 */
8
5
  url: string;
9
- /** 音乐标题 */
10
6
  title: string;
7
+ artist?: string;
8
+ album?: string;
9
+ duration?: number;
11
10
  }
12
11
  export interface MusicDetail extends MusicInfo {
13
12
  image: string;
14
13
  audio: string;
15
- duration?: number;
16
14
  }
17
- /** 音乐源配置 */
18
15
  export interface MusicSourceConfig {
19
16
  appid: number;
20
17
  package: string;
@@ -22,20 +19,6 @@ export interface MusicSourceConfig {
22
19
  sign: string;
23
20
  version: string;
24
21
  }
25
- /** QQ 音乐 API 响应 */
26
- export interface MusicQQ {
27
- id: string;
28
- mid: string;
29
- name: string;
30
- docid: string;
31
- singer: string;
32
- album?: {
33
- mid: string;
34
- name: string;
35
- };
36
- interval?: number;
37
- }
38
- /** 网易云音乐 API 响应 */
39
22
  export interface Music163 {
40
23
  id: string;
41
24
  name: string;
@@ -51,11 +34,8 @@ export interface Music163 {
51
34
  img1v1Url: string;
52
35
  };
53
36
  }
54
- /** 音乐搜索服务接口 */
55
37
  export interface MusicSearchService {
56
- /** 搜索音乐 */
57
38
  search(keyword: string, limit?: number): Promise<MusicInfo[]>;
58
- /** 获取音乐详情 */
59
39
  getDetail(id: string): Promise<MusicDetail>;
60
40
  }
61
41
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,YAAY;AACZ,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;AAE3C,aAAa;AACb,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAC,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,YAAY;AACZ,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,mBAAmB;AACnB,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mBAAmB;AACnB,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IACH,KAAK,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,eAAe;AACf,MAAM,WAAW,kBAAkB;IACjC,WAAW;IACX,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAC9D,aAAa;IACb,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAC7C"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAE9D,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IACH,KAAK,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAC9D,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAC7C"}
package/lib/types.js CHANGED
@@ -1,3 +1,2 @@
1
- // plugins/utils/music/src/types.ts
2
1
  export {};
3
2
  //# sourceMappingURL=types.js.map
package/lib/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,mCAAmC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,46 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineMiddleware } from 'zhin.js/middleware';
3
+ import { sessionKey, resolveMessageIds, getPending, clearPending } from "../lib/session.js";
4
+ import { shareMusicDetail, buildMusicShareSegment } from "../lib/music-lib.js";
5
+ import { SOURCE_DISPLAY_NAME } from "../lib/config.js";
6
+ export default defineMiddleware({
7
+ target: 'inbound',
8
+ async handle(context, next) {
9
+ const raw = context.input.content?.trim() ?? '';
10
+ if (!raw) {
11
+ await next();
12
+ return;
13
+ }
14
+ const ids = resolveMessageIds(context.input);
15
+ if (!ids) {
16
+ await next();
17
+ return;
18
+ }
19
+ const key = sessionKey(ids.endpointId, ids.conversationId, ids.senderId);
20
+ const pending = getPending(key);
21
+ if (!pending) {
22
+ await next();
23
+ return;
24
+ }
25
+ if (raw === '取消') {
26
+ clearPending(key);
27
+ await context.input.$reply('已取消点歌');
28
+ return;
29
+ }
30
+ const num = parseInt(raw, 10);
31
+ if (isNaN(num) || num < 1 || num > pending.results.length) {
32
+ await next();
33
+ return;
34
+ }
35
+ clearPending(key);
36
+ const selected = pending.results[num - 1];
37
+ const sourceName = SOURCE_DISPLAY_NAME[selected.source] ?? selected.source;
38
+ const detailResult = await shareMusicDetail(selected.id, selected.source);
39
+ if (!detailResult.success) {
40
+ await context.input.$reply(`[${sourceName}] 获取"${selected.title}"播放信息失败:${detailResult.error}`);
41
+ return;
42
+ }
43
+ const segment = buildMusicShareSegment(detailResult.music);
44
+ await context.input.$reply(segment);
45
+ },
46
+ });
@@ -0,0 +1,56 @@
1
+ import { defineMiddleware } from 'zhin.js/middleware';
2
+ import type { Message } from '@zhin.js/core/runtime';
3
+ import { sessionKey, resolveMessageIds, getPending, clearPending } from '../src/session.js';
4
+ import { shareMusicDetail, buildMusicShareSegment } from '../src/music-lib.js';
5
+ import { SOURCE_DISPLAY_NAME } from '../src/config.js';
6
+
7
+ export default defineMiddleware<Message>({
8
+ target: 'inbound',
9
+ async handle(context, next) {
10
+ const raw = context.input.content?.trim() ?? '';
11
+ if (!raw) {
12
+ await next();
13
+ return;
14
+ }
15
+
16
+ const ids = resolveMessageIds(context.input);
17
+ if (!ids) {
18
+ await next();
19
+ return;
20
+ }
21
+
22
+ const key = sessionKey(ids.endpointId, ids.conversationId, ids.senderId);
23
+ const pending = getPending(key);
24
+ if (!pending) {
25
+ await next();
26
+ return;
27
+ }
28
+
29
+ if (raw === '取消') {
30
+ clearPending(key);
31
+ await context.input.$reply('已取消点歌');
32
+ return;
33
+ }
34
+
35
+ const num = parseInt(raw, 10);
36
+ if (isNaN(num) || num < 1 || num > pending.results.length) {
37
+ await next();
38
+ return;
39
+ }
40
+
41
+ clearPending(key);
42
+ const selected = pending.results[num - 1]!;
43
+ const sourceName = SOURCE_DISPLAY_NAME[selected.source] ?? selected.source;
44
+
45
+ const detailResult = await shareMusicDetail(selected.id, selected.source);
46
+ if (!detailResult.success) {
47
+ await context.input.$reply(
48
+ `[${sourceName}] 获取"${selected.title}"播放信息失败:${detailResult.error}`,
49
+ );
50
+ return;
51
+ }
52
+
53
+ const segment = buildMusicShareSegment(detailResult.music);
54
+ await context.input.$reply(segment);
55
+ },
56
+ });