qqmusic-api-enhanced 1.0.2 → 1.0.5

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.
@@ -16,4 +16,5 @@ export default function search(query?: {
16
16
  limit?: number;
17
17
  cookie?: any;
18
18
  searchid?: string;
19
+ platform?: string;
19
20
  }, req?: typeof request): Promise<ApiResponse>;
package/module/search.js CHANGED
@@ -21,6 +21,7 @@ export default async function search(query = {}, req = request) {
21
21
  const page = Math.max(Number(query.page) || 1, 1);
22
22
  const limit = Math.min(Math.max(Number(query.limit) || 20, 1), 100);
23
23
  const searchId = query.searchid || getSearchId();
24
+ const platform = query.platform || "desktop";
24
25
  const cgiRes = await req("music.search.SearchCgiService", "DoSearchForQQMusicMobile", {
25
26
  query: keyword,
26
27
  search_type: searchType,
@@ -30,13 +31,18 @@ export default async function search(query = {}, req = request) {
30
31
  highlight: 1,
31
32
  }, {
32
33
  cookie: query.cookie,
33
- platform: "android",
34
+ platform,
34
35
  });
36
+ const rawBody = cgiRes.body || {};
37
+ const dataBody = rawBody.body || rawBody.data?.body || rawBody.data || rawBody;
38
+ const songItems = dataBody.item_song || dataBody.song?.list || dataBody.songs || [];
39
+ const songs = Array.isArray(songItems) ? songItems : (songItems.items || []);
35
40
  return {
36
41
  status: cgiRes.status,
37
42
  body: {
38
43
  code: cgiRes.body?.code ?? 200,
39
44
  data: cgiRes.body,
45
+ songs,
40
46
  },
41
47
  cookie: cgiRes.cookie,
42
48
  };
package/module/search.ts CHANGED
@@ -19,6 +19,7 @@ export default async function search(
19
19
  limit?: number;
20
20
  cookie?: any;
21
21
  searchid?: string;
22
+ platform?: string;
22
23
  } = {},
23
24
  req = request
24
25
  ): Promise<ApiResponse> {
@@ -34,6 +35,7 @@ export default async function search(
34
35
  const page = Math.max(Number(query.page) || 1, 1);
35
36
  const limit = Math.min(Math.max(Number(query.limit) || 20, 1), 100);
36
37
  const searchId = query.searchid || getSearchId();
38
+ const platform = query.platform || "desktop";
37
39
 
38
40
  const cgiRes = await req(
39
41
  "music.search.SearchCgiService",
@@ -48,15 +50,21 @@ export default async function search(
48
50
  },
49
51
  {
50
52
  cookie: query.cookie,
51
- platform: "android",
53
+ platform,
52
54
  }
53
55
  );
54
56
 
57
+ const rawBody = cgiRes.body || {};
58
+ const dataBody = rawBody.body || rawBody.data?.body || rawBody.data || rawBody;
59
+ const songItems = dataBody.item_song || dataBody.song?.list || dataBody.songs || [];
60
+ const songs = Array.isArray(songItems) ? songItems : (songItems.items || []);
61
+
55
62
  return {
56
63
  status: cgiRes.status,
57
64
  body: {
58
65
  code: cgiRes.body?.code ?? 200,
59
66
  data: cgiRes.body,
67
+ songs,
60
68
  },
61
69
  cookie: cgiRes.cookie,
62
70
  };
@@ -7,7 +7,7 @@ export interface NormalizedVipInfo {
7
7
  vipExpireTime?: number;
8
8
  }
9
9
  export declare function parseVipFromIcons(iconList?: any[], icons?: any[]): Partial<NormalizedVipInfo> | null;
10
- export declare function deriveVipInfo(body: any): NormalizedVipInfo;
10
+ export declare function deriveVipInfo(body: any, now?: number): NormalizedVipInfo;
11
11
  /**
12
12
  * 获取当前登录用户的 VIP 会员信息及身份明细.
13
13
  *
@@ -2,9 +2,33 @@ import { request } from "../util/request.js";
2
2
  import { cookieToJson } from "../util/cookie.js";
3
3
  import user_detail_fn from "./user_detail.js";
4
4
  export function parseVipFromIcons(iconList = [], icons = []) {
5
- for (const item of [...iconList, ...icons]) {
5
+ // 1. 优先从用户主页活跃佩戴的 iconList (NewIconInfo.iconlist) 查找
6
+ for (const item of iconList) {
6
7
  if (!item)
7
8
  continue;
9
+ if (item.GreyURL && String(item.GreyURL).trim().length > 0)
10
+ continue;
11
+ const url = String(item.srcUrl || item.IconURL || "");
12
+ const helptxt = String(item.Helptxt || item.Title || "");
13
+ const m = url.match(/(?:^|\/)(n)?(s?vip)(\d+)\.(?:png|webp)/i);
14
+ if (m) {
15
+ const isYear = Boolean(m[1]) || helptxt.includes("年费");
16
+ const tier = m[2].toLowerCase() === "svip" ? "svip" : "vip";
17
+ const level = parseInt(m[3], 10);
18
+ return {
19
+ vipStatus: "vip",
20
+ vipTier: tier,
21
+ vipLevel: level > 0 ? Math.min(Math.max(level, 1), 10) : 1,
22
+ vipYear: isYear,
23
+ };
24
+ }
25
+ }
26
+ // 2. 其次才从旧版快捷入口 icons 查找
27
+ for (const item of icons) {
28
+ if (!item)
29
+ continue;
30
+ if (item.GreyURL && String(item.GreyURL).trim().length > 0)
31
+ continue;
8
32
  const url = String(item.srcUrl || item.IconURL || "");
9
33
  const helptxt = String(item.Helptxt || item.Title || "");
10
34
  const m = url.match(/(?:^|\/)(n)?(s?vip)(\d+)\.(?:png|webp)/i);
@@ -22,7 +46,27 @@ export function parseVipFromIcons(iconList = [], icons = []) {
22
46
  }
23
47
  return null;
24
48
  }
25
- export function deriveVipInfo(body) {
49
+ function parseDateMs(val) {
50
+ if (val === undefined || val === null || val === "" || val === 0)
51
+ return undefined;
52
+ if (typeof val === "number" && val > 0) {
53
+ return val > 1e11 ? val : val * 1000;
54
+ }
55
+ if (typeof val === "string") {
56
+ const trimmed = val.trim();
57
+ if (!trimmed)
58
+ return undefined;
59
+ const num = Number(trimmed);
60
+ if (!isNaN(num) && num > 0) {
61
+ return num > 1e11 ? num : num * 1000;
62
+ }
63
+ const parsed = Date.parse(trimmed.replace(/-/g, "/"));
64
+ if (!isNaN(parsed))
65
+ return parsed;
66
+ }
67
+ return undefined;
68
+ }
69
+ export function deriveVipInfo(body, now = Date.now()) {
26
70
  if (!body) {
27
71
  return { vipStatus: "unknown" };
28
72
  }
@@ -33,24 +77,71 @@ export function deriveVipInfo(body) {
33
77
  const level = Number(identity.level || 0);
34
78
  const isYear = Boolean(Number(identity.HugeYearFlag || identity.yearflag || identity.is_year || identity.year_vip || 0) > 0 ||
35
79
  Number(vipData.ystar || vipData.year || 0) > 0);
80
+ // 1. 分别提取 SVIP 专有到期时间
81
+ let svipExpire = undefined;
82
+ if (vipData.starend)
83
+ svipExpire = parseDateMs(vipData.starend);
84
+ else if (vipData.ystarend)
85
+ svipExpire = parseDateMs(vipData.ystarend);
86
+ else if (vipData.send)
87
+ svipExpire = parseDateMs(vipData.send);
88
+ else if (identity.SvipEnd || identity.svip_end)
89
+ svipExpire = parseDateMs(identity.SvipEnd || identity.svip_end);
90
+ // 2. 分别提取普通 VIP / 豪华绿钻专有到期时间
91
+ let vipExpire = undefined;
92
+ if (identity.HugeVipEnd)
93
+ vipExpire = parseDateMs(identity.HugeVipEnd);
94
+ else if (identity.twelveEnd)
95
+ vipExpire = parseDateMs(identity.twelveEnd);
96
+ else if (identity.eightEnd)
97
+ vipExpire = parseDateMs(identity.eightEnd);
98
+ else if (identity.overdate)
99
+ vipExpire = parseDateMs(identity.overdate);
100
+ else if (vipData.mygreen)
101
+ vipExpire = parseDateMs(vipData.mygreen);
102
+ // 3. 通用 userinfo.expire 归集
103
+ const userinfoExpire = Number(vipData.userinfo?.expire || 0) > 0 ? parseDateMs(vipData.userinfo.expire) : undefined;
104
+ if (userinfoExpire !== undefined) {
105
+ if (svipExpire === undefined && vipExpire === undefined) {
106
+ if (svip > 0 && userinfoExpire > now) {
107
+ svipExpire = userinfoExpire;
108
+ }
109
+ else {
110
+ vipExpire = userinfoExpire;
111
+ }
112
+ }
113
+ else if (vipExpire === undefined) {
114
+ // 若已解析出 svipExpire(如已过期的 starend/send),则通用的 userinfo.expire 归属于绿钻 vipExpire
115
+ vipExpire = userinfoExpire;
116
+ }
117
+ else if (svipExpire === undefined && svip > 0) {
118
+ svipExpire = userinfoExpire;
119
+ }
120
+ }
121
+ const isSvipExpired = svipExpire !== undefined && svipExpire <= now;
122
+ const isVipExpired = vipExpire !== undefined && vipExpire <= now;
36
123
  let vipStatus = "nonVip";
37
124
  let vipTier = undefined;
38
125
  let vipLevel = undefined;
39
126
  let vipYear = undefined;
40
127
  let vipExpireTime = undefined;
41
- if (svip > 0) {
128
+ // 1. 如果存在未过期的 SVIP
129
+ if (svip > 0 && !isSvipExpired) {
42
130
  vipStatus = "vip";
43
131
  vipTier = "svip";
44
132
  vipLevel = level > 0 ? Math.min(Math.max(level, 1), 10) : 1;
45
133
  vipYear = isYear;
134
+ vipExpireTime = svipExpire ?? (vipExpire && !isVipExpired ? vipExpire : undefined);
46
135
  }
47
- else if (isVip > 0) {
136
+ else if (isVip > 0 && !isVipExpired) {
137
+ // 2. 如果存在普通 VIP(若 SVIP 已过期但 VIP 未过期,降级并展示未过期的 VIP 到期时间)
48
138
  vipStatus = "vip";
49
139
  vipTier = "vip";
50
140
  vipLevel = level > 0 ? Math.min(Math.max(level, 1), 10) : 1;
51
141
  vipYear = isYear;
142
+ vipExpireTime = vipExpire ?? (svipExpire && !isSvipExpired ? svipExpire : undefined);
52
143
  }
53
- // 若基本 identity 未命中 VIP,尝试从附加的 Info / NewIconInfo / Icons 解析
144
+ // 3. 若 identity 未命中有效 VIP(例如 SVIP 已过期,且普通 VIP 缺少基础标志或需通过勋章校准)
54
145
  if (vipStatus === "nonVip") {
55
146
  const info = vipData.Info || vipData.info || {};
56
147
  const iconList = info.NewIconInfo?.iconlist || vipData.NewIconInfo?.iconlist || [];
@@ -61,21 +152,17 @@ export function deriveVipInfo(body) {
61
152
  vipTier = iconVip.vipTier;
62
153
  vipLevel = iconVip.vipLevel;
63
154
  vipYear = iconVip.vipYear;
155
+ if (iconVip.vipTier === "vip") {
156
+ vipExpireTime = vipExpire && vipExpire > now ? vipExpire : (userinfoExpire && userinfoExpire > now ? userinfoExpire : undefined);
157
+ }
158
+ else if (iconVip.vipTier === "svip") {
159
+ vipExpireTime = svipExpire && svipExpire > now ? svipExpire : (userinfoExpire && userinfoExpire > now ? userinfoExpire : undefined);
160
+ }
64
161
  }
65
162
  }
66
- const expireTs = Number(vipData.userinfo?.expire || 0);
67
- if (expireTs > 0) {
68
- vipExpireTime = expireTs * 1000;
69
- }
70
- else if (identity.HugeVipEnd) {
71
- const parsed = Date.parse(identity.HugeVipEnd);
72
- if (!isNaN(parsed))
73
- vipExpireTime = parsed;
74
- }
75
- else if (identity.twelveEnd) {
76
- const parsed = Date.parse(identity.twelveEnd);
77
- if (!isNaN(parsed))
78
- vipExpireTime = parsed;
163
+ // 4. 严苛防线:任何已过期的到期时间绝对不允许外露
164
+ if (vipExpireTime !== undefined && vipExpireTime <= now) {
165
+ vipExpireTime = undefined;
79
166
  }
80
167
  return {
81
168
  vipStatus,
@@ -108,17 +195,21 @@ export default async function user_vip_info(query = {}, req = request) {
108
195
  }
109
196
  catch { }
110
197
  let vip = deriveVipInfo(cgiRes.body);
111
- // 若 vip_login_base 无法推断出有效 VIP,自动通过主页头部接口获取勋章母版特征
112
- if (vip.vipStatus === "nonVip" && uin && uin !== "0") {
198
+ // 若 vip_login_base 无法推断出有效 VIP,或推断出的 SVIP 已经过期,或需要主页勋章校准,
199
+ // 自动通过主页头部接口获取勋章母版特征
200
+ if ((vip.vipStatus === "nonVip" || vip.vipTier === "svip") && uin && uin !== "0") {
113
201
  try {
114
202
  const detailRes = await user_detail_fn({ uin, cookie: query.cookie }, req);
115
203
  const detailData = detailRes.body?.data || {};
116
204
  const fallbackVip = deriveVipInfo(detailData);
117
205
  if (fallbackVip.vipStatus === "vip") {
118
- vip = {
119
- ...vip,
120
- ...fallbackVip,
121
- };
206
+ if (vip.vipStatus === "nonVip" || fallbackVip.vipTier === "vip" || !vip.vipExpireTime || vip.vipExpireTime <= Date.now()) {
207
+ vip = {
208
+ ...vip,
209
+ ...fallbackVip,
210
+ vipExpireTime: (vip.vipExpireTime && vip.vipExpireTime > Date.now()) ? vip.vipExpireTime : fallbackVip.vipExpireTime,
211
+ };
212
+ }
122
213
  }
123
214
  }
124
215
  catch { }
@@ -11,8 +11,30 @@ export interface NormalizedVipInfo {
11
11
  }
12
12
 
13
13
  export function parseVipFromIcons(iconList: any[] = [], icons: any[] = []): Partial<NormalizedVipInfo> | null {
14
- for (const item of [...iconList, ...icons]) {
14
+ // 1. 优先从用户主页活跃佩戴的 iconList (NewIconInfo.iconlist) 查找
15
+ for (const item of iconList) {
15
16
  if (!item) continue;
17
+ if (item.GreyURL && String(item.GreyURL).trim().length > 0) continue;
18
+ const url = String(item.srcUrl || item.IconURL || "");
19
+ const helptxt = String(item.Helptxt || item.Title || "");
20
+ const m = url.match(/(?:^|\/)(n)?(s?vip)(\d+)\.(?:png|webp)/i);
21
+ if (m) {
22
+ const isYear = Boolean(m[1]) || helptxt.includes("年费");
23
+ const tier = m[2].toLowerCase() === "svip" ? "svip" : "vip";
24
+ const level = parseInt(m[3], 10);
25
+ return {
26
+ vipStatus: "vip",
27
+ vipTier: tier,
28
+ vipLevel: level > 0 ? Math.min(Math.max(level, 1), 10) : 1,
29
+ vipYear: isYear,
30
+ };
31
+ }
32
+ }
33
+
34
+ // 2. 其次才从旧版快捷入口 icons 查找
35
+ for (const item of icons) {
36
+ if (!item) continue;
37
+ if (item.GreyURL && String(item.GreyURL).trim().length > 0) continue;
16
38
  const url = String(item.srcUrl || item.IconURL || "");
17
39
  const helptxt = String(item.Helptxt || item.Title || "");
18
40
  const m = url.match(/(?:^|\/)(n)?(s?vip)(\d+)\.(?:png|webp)/i);
@@ -31,7 +53,25 @@ export function parseVipFromIcons(iconList: any[] = [], icons: any[] = []): Part
31
53
  return null;
32
54
  }
33
55
 
34
- export function deriveVipInfo(body: any): NormalizedVipInfo {
56
+ function parseDateMs(val: any): number | undefined {
57
+ if (val === undefined || val === null || val === "" || val === 0) return undefined;
58
+ if (typeof val === "number" && val > 0) {
59
+ return val > 1e11 ? val : val * 1000;
60
+ }
61
+ if (typeof val === "string") {
62
+ const trimmed = val.trim();
63
+ if (!trimmed) return undefined;
64
+ const num = Number(trimmed);
65
+ if (!isNaN(num) && num > 0) {
66
+ return num > 1e11 ? num : num * 1000;
67
+ }
68
+ const parsed = Date.parse(trimmed.replace(/-/g, "/"));
69
+ if (!isNaN(parsed)) return parsed;
70
+ }
71
+ return undefined;
72
+ }
73
+
74
+ export function deriveVipInfo(body: any, now = Date.now()): NormalizedVipInfo {
35
75
  if (!body) {
36
76
  return { vipStatus: "unknown" };
37
77
  }
@@ -45,25 +85,64 @@ export function deriveVipInfo(body: any): NormalizedVipInfo {
45
85
  Number(vipData.ystar || vipData.year || 0) > 0
46
86
  );
47
87
 
88
+ // 1. 分别提取 SVIP 专有到期时间
89
+ let svipExpire: number | undefined = undefined;
90
+ if (vipData.starend) svipExpire = parseDateMs(vipData.starend);
91
+ else if (vipData.ystarend) svipExpire = parseDateMs(vipData.ystarend);
92
+ else if (vipData.send) svipExpire = parseDateMs(vipData.send);
93
+ else if (identity.SvipEnd || identity.svip_end) svipExpire = parseDateMs(identity.SvipEnd || identity.svip_end);
94
+
95
+ // 2. 分别提取普通 VIP / 豪华绿钻专有到期时间
96
+ let vipExpire: number | undefined = undefined;
97
+ if (identity.HugeVipEnd) vipExpire = parseDateMs(identity.HugeVipEnd);
98
+ else if (identity.twelveEnd) vipExpire = parseDateMs(identity.twelveEnd);
99
+ else if (identity.eightEnd) vipExpire = parseDateMs(identity.eightEnd);
100
+ else if (identity.overdate) vipExpire = parseDateMs(identity.overdate);
101
+ else if (vipData.mygreen) vipExpire = parseDateMs(vipData.mygreen);
102
+
103
+ // 3. 通用 userinfo.expire 归集
104
+ const userinfoExpire = Number(vipData.userinfo?.expire || 0) > 0 ? parseDateMs(vipData.userinfo.expire) : undefined;
105
+ if (userinfoExpire !== undefined) {
106
+ if (svipExpire === undefined && vipExpire === undefined) {
107
+ if (svip > 0 && userinfoExpire > now) {
108
+ svipExpire = userinfoExpire;
109
+ } else {
110
+ vipExpire = userinfoExpire;
111
+ }
112
+ } else if (vipExpire === undefined) {
113
+ // 若已解析出 svipExpire(如已过期的 starend/send),则通用的 userinfo.expire 归属于绿钻 vipExpire
114
+ vipExpire = userinfoExpire;
115
+ } else if (svipExpire === undefined && svip > 0) {
116
+ svipExpire = userinfoExpire;
117
+ }
118
+ }
119
+
120
+ const isSvipExpired = svipExpire !== undefined && svipExpire <= now;
121
+ const isVipExpired = vipExpire !== undefined && vipExpire <= now;
122
+
48
123
  let vipStatus: "vip" | "nonVip" | "unknown" = "nonVip";
49
124
  let vipTier: "svip" | "vip" | undefined = undefined;
50
125
  let vipLevel: number | undefined = undefined;
51
126
  let vipYear: boolean | undefined = undefined;
52
127
  let vipExpireTime: number | undefined = undefined;
53
128
 
54
- if (svip > 0) {
129
+ // 1. 如果存在未过期的 SVIP
130
+ if (svip > 0 && !isSvipExpired) {
55
131
  vipStatus = "vip";
56
132
  vipTier = "svip";
57
133
  vipLevel = level > 0 ? Math.min(Math.max(level, 1), 10) : 1;
58
134
  vipYear = isYear;
59
- } else if (isVip > 0) {
135
+ vipExpireTime = svipExpire ?? (vipExpire && !isVipExpired ? vipExpire : undefined);
136
+ } else if (isVip > 0 && !isVipExpired) {
137
+ // 2. 如果存在普通 VIP(若 SVIP 已过期但 VIP 未过期,降级并展示未过期的 VIP 到期时间)
60
138
  vipStatus = "vip";
61
139
  vipTier = "vip";
62
140
  vipLevel = level > 0 ? Math.min(Math.max(level, 1), 10) : 1;
63
141
  vipYear = isYear;
142
+ vipExpireTime = vipExpire ?? (svipExpire && !isSvipExpired ? svipExpire : undefined);
64
143
  }
65
144
 
66
- // 若基本 identity 未命中 VIP,尝试从附加的 Info / NewIconInfo / Icons 解析
145
+ // 3. 若 identity 未命中有效 VIP(例如 SVIP 已过期,且普通 VIP 缺少基础标志或需通过勋章校准)
67
146
  if (vipStatus === "nonVip") {
68
147
  const info = vipData.Info || vipData.info || {};
69
148
  const iconList = info.NewIconInfo?.iconlist || vipData.NewIconInfo?.iconlist || [];
@@ -74,18 +153,17 @@ export function deriveVipInfo(body: any): NormalizedVipInfo {
74
153
  vipTier = iconVip.vipTier;
75
154
  vipLevel = iconVip.vipLevel;
76
155
  vipYear = iconVip.vipYear;
156
+ if (iconVip.vipTier === "vip") {
157
+ vipExpireTime = vipExpire && vipExpire > now ? vipExpire : (userinfoExpire && userinfoExpire > now ? userinfoExpire : undefined);
158
+ } else if (iconVip.vipTier === "svip") {
159
+ vipExpireTime = svipExpire && svipExpire > now ? svipExpire : (userinfoExpire && userinfoExpire > now ? userinfoExpire : undefined);
160
+ }
77
161
  }
78
162
  }
79
163
 
80
- const expireTs = Number(vipData.userinfo?.expire || 0);
81
- if (expireTs > 0) {
82
- vipExpireTime = expireTs * 1000;
83
- } else if (identity.HugeVipEnd) {
84
- const parsed = Date.parse(identity.HugeVipEnd);
85
- if (!isNaN(parsed)) vipExpireTime = parsed;
86
- } else if (identity.twelveEnd) {
87
- const parsed = Date.parse(identity.twelveEnd);
88
- if (!isNaN(parsed)) vipExpireTime = parsed;
164
+ // 4. 严苛防线:任何已过期的到期时间绝对不允许外露
165
+ if (vipExpireTime !== undefined && vipExpireTime <= now) {
166
+ vipExpireTime = undefined;
89
167
  }
90
168
 
91
169
  return {
@@ -131,17 +209,21 @@ export default async function user_vip_info(
131
209
 
132
210
  let vip = deriveVipInfo(cgiRes.body);
133
211
 
134
- // 若 vip_login_base 无法推断出有效 VIP,自动通过主页头部接口获取勋章母版特征
135
- if (vip.vipStatus === "nonVip" && uin && uin !== "0") {
212
+ // 若 vip_login_base 无法推断出有效 VIP,或推断出的 SVIP 已经过期,或需要主页勋章校准,
213
+ // 自动通过主页头部接口获取勋章母版特征
214
+ if ((vip.vipStatus === "nonVip" || vip.vipTier === "svip") && uin && uin !== "0") {
136
215
  try {
137
216
  const detailRes = await user_detail_fn({ uin, cookie: query.cookie }, req);
138
217
  const detailData = detailRes.body?.data || {};
139
218
  const fallbackVip = deriveVipInfo(detailData);
140
219
  if (fallbackVip.vipStatus === "vip") {
141
- vip = {
142
- ...vip,
143
- ...fallbackVip,
144
- };
220
+ if (vip.vipStatus === "nonVip" || fallbackVip.vipTier === "vip" || !vip.vipExpireTime || vip.vipExpireTime <= Date.now()) {
221
+ vip = {
222
+ ...vip,
223
+ ...fallbackVip,
224
+ vipExpireTime: (vip.vipExpireTime && vip.vipExpireTime > Date.now()) ? vip.vipExpireTime : fallbackVip.vipExpireTime,
225
+ };
226
+ }
145
227
  }
146
228
  } catch {}
147
229
  }
@@ -156,3 +238,4 @@ export default async function user_vip_info(
156
238
  cookie: cgiRes.cookie,
157
239
  };
158
240
  }
241
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qqmusic-api-enhanced",
3
- "version": "1.0.2",
3
+ "version": "1.0.5",
4
4
  "description": "QQ音乐增强版API,支持扫码登录/凭证刷新/直链提取/歌词解密/歌单歌手检索 || QQ Music Enhanced API for Node.js & Bun",
5
5
  "type": "module",
6
6
  "main": "main.js",