qqmusic-api-enhanced 1.0.1 → 1.0.2

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.
@@ -35,21 +35,27 @@ export default async function login_status(
35
35
  req = request
36
36
  ): Promise<ApiResponse<LoginStatusResult>> {
37
37
  const cookieObj = cookieToJson(query.cookie);
38
- let uin = cookieObj.uin || cookieObj.qqmusic_uin || cookieObj.wxuin || "";
38
+ let uin = cookieObj.uin || cookieObj.qqmusic_uin || cookieObj.musicid || cookieObj.wxuin || "";
39
+ const musickey = cookieObj.qm_keyst || cookieObj.qqmusic_key || cookieObj.musickey || "";
39
40
 
40
- const cgiRes = await req(
41
- "music.UserInfo.userInfoServer",
42
- "GetLoginUserInfo",
43
- {},
44
- {
45
- cookie: query.cookie,
46
- platform: "web",
47
- }
48
- );
41
+ let cgiRes: any = { status: 200, body: {} };
42
+ try {
43
+ cgiRes = await req(
44
+ "music.UserInfo.userInfoServer",
45
+ "GetLoginUserInfo",
46
+ {},
47
+ {
48
+ cookie: query.cookie,
49
+ platform: "android",
50
+ }
51
+ );
52
+ } catch {}
49
53
 
50
54
  const data = (cgiRes.body || {}) as any;
51
55
  const userData = data.user || data.userInfo || data;
52
- const isLogin = data.code === 0 && Boolean(userData.uin || userData.encryptUin || uin);
56
+ let isLogin =
57
+ (data.code === 0 || (data.code === undefined && Boolean(userData.uin || userData.encryptUin))) &&
58
+ Boolean(userData.uin || userData.encryptUin || uin);
53
59
 
54
60
  if (userData.uin) {
55
61
  uin = String(userData.uin).trim();
@@ -60,13 +66,16 @@ export default async function login_status(
60
66
  let nickname = userData.nick || userData.nickname || "";
61
67
  let avatarUrl: string | undefined = userData.headurl || userData.avatar;
62
68
 
63
- // 若基本信息不全且处于已登录状态,尝试从 user_detail 补全昵称与头像
64
- if (isLogin && (!nickname || !avatarUrl)) {
69
+ // 若基本信息不全,只要有 uin,调用 user_detail 补全真实昵称与高清头像
70
+ if (uin && (!nickname || !avatarUrl)) {
65
71
  try {
66
72
  const detailRes = await user_detail_fn({ uin, cookie: query.cookie }, req);
67
- const header = detailRes.body?.data?.data || detailRes.body?.data || {};
68
- if (header.nick && !nickname) nickname = header.nick;
69
- if (header.headurl && !avatarUrl) avatarUrl = header.headurl;
73
+ const detailData = detailRes.body?.data || {};
74
+ if (detailData.nick && !nickname) nickname = detailData.nick;
75
+ if (detailData.headurl && !avatarUrl) avatarUrl = detailData.headurl;
76
+ if (detailData.nick && Boolean(musickey || uin)) {
77
+ isLogin = true;
78
+ }
70
79
  } catch {}
71
80
  }
72
81
 
@@ -76,9 +85,9 @@ export default async function login_status(
76
85
 
77
86
  // 补全 VIP 会员信息
78
87
  let vip: NormalizedVipInfo = { vipStatus: "nonVip" };
79
- if (isLogin) {
88
+ if (isLogin || uin) {
80
89
  try {
81
- const vipRes = await user_vip_info_fn({ cookie: query.cookie }, req);
90
+ const vipRes = await user_vip_info_fn({ cookie: query.cookie, uin }, req);
82
91
  vip = vipRes.body.vip;
83
92
  } catch {
84
93
  vip = { vipStatus: "unknown" };
@@ -97,7 +106,7 @@ export default async function login_status(
97
106
  };
98
107
 
99
108
  return {
100
- status: cgiRes.status,
109
+ status: cgiRes.status || 200,
101
110
  body: {
102
111
  code: isLogin ? 200 : 301,
103
112
  isLogin,
@@ -11,19 +11,42 @@ export default async function user_detail(query = {}, req = request) {
11
11
  const targetUin = query.uin?.toString() ||
12
12
  cookieObj.uin ||
13
13
  cookieObj.qqmusic_uin ||
14
+ cookieObj.musicid ||
14
15
  cookieObj.wxuin ||
16
+ cookieObj.euin ||
15
17
  "0";
16
- const cgiRes = await req("music.userHomepage.UserHomepage", "GetHomepageHeader", {
17
- uin: Number(targetUin) || 0,
18
+ const cgiRes = await req("music.UnifiedHomepage.UnifiedHomepageSrv", "GetHomepageHeader", {
19
+ uin: targetUin,
20
+ IsQueryTabDetail: 1,
18
21
  }, {
22
+ uin: targetUin,
19
23
  cookie: query.cookie,
20
- platform: "web",
24
+ platform: "android",
21
25
  });
26
+ const rawData = cgiRes.body?.data || cgiRes.body || {};
27
+ const info = rawData.Info || rawData.info || {};
28
+ const baseInfo = info.BaseInfo || info.base_info || {};
29
+ const newIconInfo = info.NewIconInfo || info.new_icon_info || {};
30
+ const icons = info.Icons || info.icons || [];
31
+ const nick = String(baseInfo.Name || baseInfo.name || "").trim();
32
+ const avatarUrl = String(baseInfo.BigAvatar || baseInfo.Avatar || baseInfo.avatar || "").trim();
33
+ const formattedData = {
34
+ ...rawData,
35
+ nick,
36
+ headurl: avatarUrl,
37
+ avatar: avatarUrl,
38
+ BaseInfo: baseInfo,
39
+ NewIconInfo: newIconInfo,
40
+ Icons: icons,
41
+ Info: info,
42
+ };
22
43
  return {
23
44
  status: cgiRes.status,
24
45
  body: {
25
46
  code: cgiRes.body?.code ?? 200,
26
- data: cgiRes.body,
47
+ data: formattedData,
48
+ nick,
49
+ avatarUrl,
27
50
  },
28
51
  cookie: cgiRes.cookie,
29
52
  };
@@ -16,26 +16,52 @@ export default async function user_detail(
16
16
  query.uin?.toString() ||
17
17
  cookieObj.uin ||
18
18
  cookieObj.qqmusic_uin ||
19
+ cookieObj.musicid ||
19
20
  cookieObj.wxuin ||
21
+ cookieObj.euin ||
20
22
  "0";
21
23
 
22
24
  const cgiRes = await req(
23
- "music.userHomepage.UserHomepage",
25
+ "music.UnifiedHomepage.UnifiedHomepageSrv",
24
26
  "GetHomepageHeader",
25
27
  {
26
- uin: Number(targetUin) || 0,
28
+ uin: targetUin,
29
+ IsQueryTabDetail: 1,
27
30
  },
28
31
  {
32
+ uin: targetUin,
29
33
  cookie: query.cookie,
30
- platform: "web",
34
+ platform: "android",
31
35
  }
32
36
  );
33
37
 
38
+ const rawData = cgiRes.body?.data || cgiRes.body || {};
39
+ const info = rawData.Info || rawData.info || {};
40
+ const baseInfo = info.BaseInfo || info.base_info || {};
41
+ const newIconInfo = info.NewIconInfo || info.new_icon_info || {};
42
+ const icons = info.Icons || info.icons || [];
43
+
44
+ const nick = String(baseInfo.Name || baseInfo.name || "").trim();
45
+ const avatarUrl = String(baseInfo.BigAvatar || baseInfo.Avatar || baseInfo.avatar || "").trim();
46
+
47
+ const formattedData = {
48
+ ...rawData,
49
+ nick,
50
+ headurl: avatarUrl,
51
+ avatar: avatarUrl,
52
+ BaseInfo: baseInfo,
53
+ NewIconInfo: newIconInfo,
54
+ Icons: icons,
55
+ Info: info,
56
+ };
57
+
34
58
  return {
35
59
  status: cgiRes.status,
36
60
  body: {
37
61
  code: cgiRes.body?.code ?? 200,
38
- data: cgiRes.body,
62
+ data: formattedData,
63
+ nick,
64
+ avatarUrl,
39
65
  },
40
66
  cookie: cgiRes.cookie,
41
67
  };
@@ -6,14 +6,17 @@ export interface NormalizedVipInfo {
6
6
  vipYear?: boolean;
7
7
  vipExpireTime?: number;
8
8
  }
9
+ export declare function parseVipFromIcons(iconList?: any[], icons?: any[]): Partial<NormalizedVipInfo> | null;
9
10
  export declare function deriveVipInfo(body: any): NormalizedVipInfo;
10
11
  /**
11
12
  * 获取当前登录用户的 VIP 会员信息及身份明细.
12
13
  *
13
14
  * @param query.cookie 登录 Cookie
15
+ * @param query.uin 用户 QQ/UIN
14
16
  */
15
17
  export default function user_vip_info(query?: {
16
18
  cookie?: any;
19
+ uin?: string | number;
17
20
  }, req?: typeof request): Promise<ApiResponse<{
18
21
  code: number;
19
22
  data: any;
@@ -1,4 +1,27 @@
1
1
  import { request } from "../util/request.js";
2
+ import { cookieToJson } from "../util/cookie.js";
3
+ import user_detail_fn from "./user_detail.js";
4
+ export function parseVipFromIcons(iconList = [], icons = []) {
5
+ for (const item of [...iconList, ...icons]) {
6
+ if (!item)
7
+ continue;
8
+ const url = String(item.srcUrl || item.IconURL || "");
9
+ const helptxt = String(item.Helptxt || item.Title || "");
10
+ const m = url.match(/(?:^|\/)(n)?(s?vip)(\d+)\.(?:png|webp)/i);
11
+ if (m) {
12
+ const isYear = Boolean(m[1]) || helptxt.includes("年费");
13
+ const tier = m[2].toLowerCase() === "svip" ? "svip" : "vip";
14
+ const level = parseInt(m[3], 10);
15
+ return {
16
+ vipStatus: "vip",
17
+ vipTier: tier,
18
+ vipLevel: level > 0 ? Math.min(Math.max(level, 1), 10) : 1,
19
+ vipYear: isYear,
20
+ };
21
+ }
22
+ }
23
+ return null;
24
+ }
2
25
  export function deriveVipInfo(body) {
3
26
  if (!body) {
4
27
  return { vipStatus: "unknown" };
@@ -8,8 +31,8 @@ export function deriveVipInfo(body) {
8
31
  const svip = Number(vipData.svip || 0);
9
32
  const isVip = Number(identity.HugeVip || identity.vip || 0);
10
33
  const level = Number(identity.level || 0);
11
- const isYear = Boolean(Number(identity.is_year || identity.year_vip || identity.HugeVipYear || identity.year || 0) > 0 ||
12
- Number(vipData.year || vipData.is_year || 0) > 0);
34
+ const isYear = Boolean(Number(identity.HugeYearFlag || identity.yearflag || identity.is_year || identity.year_vip || 0) > 0 ||
35
+ Number(vipData.ystar || vipData.year || 0) > 0);
13
36
  let vipStatus = "nonVip";
14
37
  let vipTier = undefined;
15
38
  let vipLevel = undefined;
@@ -27,6 +50,19 @@ export function deriveVipInfo(body) {
27
50
  vipLevel = level > 0 ? Math.min(Math.max(level, 1), 10) : 1;
28
51
  vipYear = isYear;
29
52
  }
53
+ // 若基本 identity 未命中 VIP,尝试从附加的 Info / NewIconInfo / Icons 解析
54
+ if (vipStatus === "nonVip") {
55
+ const info = vipData.Info || vipData.info || {};
56
+ const iconList = info.NewIconInfo?.iconlist || vipData.NewIconInfo?.iconlist || [];
57
+ const icons = info.Icons || vipData.Icons || [];
58
+ const iconVip = parseVipFromIcons(iconList, icons);
59
+ if (iconVip && iconVip.vipStatus === "vip") {
60
+ vipStatus = "vip";
61
+ vipTier = iconVip.vipTier;
62
+ vipLevel = iconVip.vipLevel;
63
+ vipYear = iconVip.vipYear;
64
+ }
65
+ }
30
66
  const expireTs = Number(vipData.userinfo?.expire || 0);
31
67
  if (expireTs > 0) {
32
68
  vipExpireTime = expireTs * 1000;
@@ -53,13 +89,40 @@ export function deriveVipInfo(body) {
53
89
  * 获取当前登录用户的 VIP 会员信息及身份明细.
54
90
  *
55
91
  * @param query.cookie 登录 Cookie
92
+ * @param query.uin 用户 QQ/UIN
56
93
  */
57
94
  export default async function user_vip_info(query = {}, req = request) {
58
- const cgiRes = await req("VipLogin.VipLoginInter", "vip_login_base", {}, {
59
- cookie: query.cookie,
60
- platform: "web",
61
- });
62
- const vip = deriveVipInfo(cgiRes.body);
95
+ const cookieObj = cookieToJson(query.cookie);
96
+ const uin = query.uin?.toString() ||
97
+ cookieObj.uin ||
98
+ cookieObj.qqmusic_uin ||
99
+ cookieObj.musicid ||
100
+ "0";
101
+ let cgiRes = { status: 200, body: {} };
102
+ try {
103
+ cgiRes = await req("VipLogin.VipLoginInter", "vip_login_base", {}, {
104
+ uin,
105
+ cookie: query.cookie,
106
+ platform: "android",
107
+ });
108
+ }
109
+ catch { }
110
+ let vip = deriveVipInfo(cgiRes.body);
111
+ // 若 vip_login_base 无法推断出有效 VIP,自动通过主页头部接口获取勋章母版特征
112
+ if (vip.vipStatus === "nonVip" && uin && uin !== "0") {
113
+ try {
114
+ const detailRes = await user_detail_fn({ uin, cookie: query.cookie }, req);
115
+ const detailData = detailRes.body?.data || {};
116
+ const fallbackVip = deriveVipInfo(detailData);
117
+ if (fallbackVip.vipStatus === "vip") {
118
+ vip = {
119
+ ...vip,
120
+ ...fallbackVip,
121
+ };
122
+ }
123
+ }
124
+ catch { }
125
+ }
63
126
  return {
64
127
  status: cgiRes.status,
65
128
  body: {
@@ -1,4 +1,6 @@
1
1
  import { request, type ApiResponse } from "../util/request.js";
2
+ import { cookieToJson } from "../util/cookie.js";
3
+ import user_detail_fn from "./user_detail.js";
2
4
 
3
5
  export interface NormalizedVipInfo {
4
6
  vipStatus: "vip" | "nonVip" | "unknown";
@@ -8,6 +10,27 @@ export interface NormalizedVipInfo {
8
10
  vipExpireTime?: number;
9
11
  }
10
12
 
13
+ export function parseVipFromIcons(iconList: any[] = [], icons: any[] = []): Partial<NormalizedVipInfo> | null {
14
+ for (const item of [...iconList, ...icons]) {
15
+ if (!item) continue;
16
+ const url = String(item.srcUrl || item.IconURL || "");
17
+ const helptxt = String(item.Helptxt || item.Title || "");
18
+ const m = url.match(/(?:^|\/)(n)?(s?vip)(\d+)\.(?:png|webp)/i);
19
+ if (m) {
20
+ const isYear = Boolean(m[1]) || helptxt.includes("年费");
21
+ const tier = m[2].toLowerCase() === "svip" ? "svip" : "vip";
22
+ const level = parseInt(m[3], 10);
23
+ return {
24
+ vipStatus: "vip",
25
+ vipTier: tier,
26
+ vipLevel: level > 0 ? Math.min(Math.max(level, 1), 10) : 1,
27
+ vipYear: isYear,
28
+ };
29
+ }
30
+ }
31
+ return null;
32
+ }
33
+
11
34
  export function deriveVipInfo(body: any): NormalizedVipInfo {
12
35
  if (!body) {
13
36
  return { vipStatus: "unknown" };
@@ -18,8 +41,8 @@ export function deriveVipInfo(body: any): NormalizedVipInfo {
18
41
  const isVip = Number(identity.HugeVip || identity.vip || 0);
19
42
  const level = Number(identity.level || 0);
20
43
  const isYear = Boolean(
21
- Number(identity.is_year || identity.year_vip || identity.HugeVipYear || identity.year || 0) > 0 ||
22
- Number(vipData.year || vipData.is_year || 0) > 0
44
+ Number(identity.HugeYearFlag || identity.yearflag || identity.is_year || identity.year_vip || 0) > 0 ||
45
+ Number(vipData.ystar || vipData.year || 0) > 0
23
46
  );
24
47
 
25
48
  let vipStatus: "vip" | "nonVip" | "unknown" = "nonVip";
@@ -40,6 +63,20 @@ export function deriveVipInfo(body: any): NormalizedVipInfo {
40
63
  vipYear = isYear;
41
64
  }
42
65
 
66
+ // 若基本 identity 未命中 VIP,尝试从附加的 Info / NewIconInfo / Icons 解析
67
+ if (vipStatus === "nonVip") {
68
+ const info = vipData.Info || vipData.info || {};
69
+ const iconList = info.NewIconInfo?.iconlist || vipData.NewIconInfo?.iconlist || [];
70
+ const icons = info.Icons || vipData.Icons || [];
71
+ const iconVip = parseVipFromIcons(iconList, icons);
72
+ if (iconVip && iconVip.vipStatus === "vip") {
73
+ vipStatus = "vip";
74
+ vipTier = iconVip.vipTier;
75
+ vipLevel = iconVip.vipLevel;
76
+ vipYear = iconVip.vipYear;
77
+ }
78
+ }
79
+
43
80
  const expireTs = Number(vipData.userinfo?.expire || 0);
44
81
  if (expireTs > 0) {
45
82
  vipExpireTime = expireTs * 1000;
@@ -64,22 +101,50 @@ export function deriveVipInfo(body: any): NormalizedVipInfo {
64
101
  * 获取当前登录用户的 VIP 会员信息及身份明细.
65
102
  *
66
103
  * @param query.cookie 登录 Cookie
104
+ * @param query.uin 用户 QQ/UIN
67
105
  */
68
106
  export default async function user_vip_info(
69
- query: { cookie?: any } = {},
107
+ query: { cookie?: any; uin?: string | number } = {},
70
108
  req = request
71
109
  ): Promise<ApiResponse<{ code: number; data: any; vip: NormalizedVipInfo }>> {
72
- const cgiRes = await req(
73
- "VipLogin.VipLoginInter",
74
- "vip_login_base",
75
- {},
76
- {
77
- cookie: query.cookie,
78
- platform: "web",
79
- }
80
- );
110
+ const cookieObj = cookieToJson(query.cookie);
111
+ const uin =
112
+ query.uin?.toString() ||
113
+ cookieObj.uin ||
114
+ cookieObj.qqmusic_uin ||
115
+ cookieObj.musicid ||
116
+ "0";
81
117
 
82
- const vip = deriveVipInfo(cgiRes.body);
118
+ let cgiRes: ApiResponse<any> = { status: 200, body: {} };
119
+ try {
120
+ cgiRes = await req(
121
+ "VipLogin.VipLoginInter",
122
+ "vip_login_base",
123
+ {},
124
+ {
125
+ uin,
126
+ cookie: query.cookie,
127
+ platform: "android",
128
+ }
129
+ );
130
+ } catch {}
131
+
132
+ let vip = deriveVipInfo(cgiRes.body);
133
+
134
+ // 若 vip_login_base 无法推断出有效 VIP,自动通过主页头部接口获取勋章母版特征
135
+ if (vip.vipStatus === "nonVip" && uin && uin !== "0") {
136
+ try {
137
+ const detailRes = await user_detail_fn({ uin, cookie: query.cookie }, req);
138
+ const detailData = detailRes.body?.data || {};
139
+ const fallbackVip = deriveVipInfo(detailData);
140
+ if (fallbackVip.vipStatus === "vip") {
141
+ vip = {
142
+ ...vip,
143
+ ...fallbackVip,
144
+ };
145
+ }
146
+ } catch {}
147
+ }
83
148
 
84
149
  return {
85
150
  status: cgiRes.status,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qqmusic-api-enhanced",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "QQ音乐增强版API,支持扫码登录/凭证刷新/直链提取/歌词解密/歌单歌手检索 || QQ Music Enhanced API for Node.js & Bun",
5
5
  "type": "module",
6
6
  "main": "main.js",
@@ -4,6 +4,8 @@ export interface MobileLoginState {
4
4
  message: string;
5
5
  uin?: string;
6
6
  musickey?: string;
7
+ nickname?: string;
8
+ avatarUrl?: string;
7
9
  cookieStr?: string;
8
10
  createdAt: number;
9
11
  client?: mqtt.MqttClient;
@@ -4,7 +4,8 @@ import mqtt from "mqtt";
4
4
  import { requestCgi } from "./request.js";
5
5
  import { cookieToString, parseSetCookie } from "./cookie.js";
6
6
  // Polyfill ws.createWebSocketStream for Bun runtime
7
- if (typeof ws.createWebSocketStream !== "function") {
7
+ const isBun = typeof globalThis.Bun !== "undefined";
8
+ if (isBun || typeof ws.createWebSocketStream !== "function") {
8
9
  ws.createWebSocketStream = function (socket) {
9
10
  const duplex = new Duplex({
10
11
  read() { },
@@ -27,6 +28,12 @@ const mobileSessions = new Map();
27
28
  export function registerMobileSession(qrcodeId) {
28
29
  if (!qrcodeId)
29
30
  return;
31
+ const existing = mobileSessions.get(qrcodeId);
32
+ if (existing && existing.code === 200)
33
+ return;
34
+ if (existing && Date.now() - existing.createdAt < 120_000 && existing.client && !existing.client.disconnected) {
35
+ return;
36
+ }
30
37
  const now = Date.now();
31
38
  for (const [key, s] of mobileSessions.entries()) {
32
39
  if (now - s.createdAt > 300_000) {
@@ -109,26 +116,66 @@ export function registerMobileSession(qrcodeId) {
109
116
  }
110
117
  else if (type === "cookies") {
111
118
  const cookies = payload?.cookies || {};
112
- const uin = cookies.qqmusic_uin?.value;
113
- const key = cookies.qqmusic_key?.value;
119
+ const uin = cookies.qqmusic_uin?.value || cookies.uin?.value || payload?.uin;
120
+ const key = cookies.qqmusic_key?.value || cookies.qm_keyst?.value || payload?.musickey;
114
121
  if (uin && key) {
115
- const loginRes = await requestCgi("music.login.LoginServer", "Login", {
116
- musicid: Number(uin),
117
- qrCodeID: qrcodeId,
118
- token: String(key),
119
- }, { platform: "android" });
120
- const resultCookies = parseSetCookie(loginRes.cookie || []);
122
+ let loginData = null;
123
+ let resultCookies = {};
124
+ try {
125
+ const loginRes = await requestCgi("music.login.LoginServer", "Login", {
126
+ musicid: Number(uin),
127
+ qrCodeID: qrcodeId,
128
+ token: String(key),
129
+ }, {
130
+ platform: "android",
131
+ comm: { tmeLoginType: 6 },
132
+ });
133
+ loginData = loginRes.body;
134
+ resultCookies = parseSetCookie(loginRes.cookie || []);
135
+ }
136
+ catch { }
137
+ const realMusickey = String(loginData?.musickey || key);
138
+ const realUin = String(loginData?.musicid || uin);
139
+ const nick = String(loginData?.nick || "").trim();
140
+ const logo = String(loginData?.logo || "").trim();
141
+ const encryptUin = String(loginData?.encryptUin || cookies.euin?.value || "");
142
+ const refreshToken = String(loginData?.refresh_token || "");
143
+ const accessToken = String(loginData?.access_token || "");
144
+ const loginType = String(loginData?.loginType || 2);
121
145
  const cookieObj = {
122
- uin: String(uin),
123
- qqmusic_uin: String(uin),
124
- qm_keyst: String(key),
125
- qqmusic_key: String(key),
126
- ...resultCookies,
146
+ uin: realUin,
147
+ qqmusic_uin: realUin,
148
+ musicid: realUin,
149
+ qm_keyst: realMusickey,
150
+ qqmusic_key: realMusickey,
151
+ musickey: realMusickey,
152
+ tmeAppID: "qqmusic",
153
+ tmeLoginType: loginType,
127
154
  };
155
+ if (encryptUin) {
156
+ cookieObj.euin = encryptUin;
157
+ cookieObj.encryptUin = encryptUin;
158
+ }
159
+ if (refreshToken) {
160
+ cookieObj.refresh_token = refreshToken;
161
+ }
162
+ if (accessToken) {
163
+ cookieObj.access_token = accessToken;
164
+ }
165
+ for (const [cookieName, cookieItem] of Object.entries(cookies)) {
166
+ if (cookieItem && typeof cookieItem.value === "string" && !cookieObj[cookieName]) {
167
+ cookieObj[cookieName] = cookieItem.value;
168
+ }
169
+ }
170
+ Object.assign(cookieObj, resultCookies);
128
171
  state.code = 200;
129
172
  state.message = "登录成功";
130
- state.uin = String(uin);
131
- state.musickey = String(key);
173
+ state.uin = realUin;
174
+ state.musickey = realMusickey;
175
+ if (nick)
176
+ state.nickname = nick;
177
+ if (logo)
178
+ state.avatarUrl = logo;
132
179
  state.cookieStr = cookieToString(cookieObj);
133
180
  try {
134
181
  client.end(true);