qwenproxy-cli 1.4.2 → 1.4.7

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.
package/dist/index.js CHANGED
@@ -4996,8 +4996,29 @@ function getStealthScript(profile) {
4996
4996
  const _toBlob = HTMLCanvasElement.prototype.toBlob;
4997
4997
  const _getImageData = CanvasRenderingContext2D.prototype.getImageData;
4998
4998
 
4999
+ function isCaptchaCanvas(canvas) {
5000
+ try {
5001
+ if (!canvas) return false;
5002
+ const id = (canvas.id || "").toLowerCase();
5003
+ const cls = (canvas.className || "").toLowerCase();
5004
+ return (
5005
+ id.includes("baxia") ||
5006
+ id.includes("nc_") ||
5007
+ id.includes("captcha") ||
5008
+ id.includes("punish") ||
5009
+ cls.includes("baxia") ||
5010
+ cls.includes("nc_") ||
5011
+ cls.includes("captcha") ||
5012
+ Boolean(canvas.closest?.("#baxia-dialog, #baxia-punish, [class*='baxia'], [class*='nc_'], .auth-layout"))
5013
+ );
5014
+ } catch(e) {
5015
+ return false;
5016
+ }
5017
+ }
5018
+
4999
5019
  function addNoise(canvas) {
5000
5020
  try {
5021
+ if (isCaptchaCanvas(canvas)) return;
5001
5022
  const ctx = canvas.getContext('2d');
5002
5023
  if (!ctx) return;
5003
5024
  const style = ctx.fillStyle;
@@ -5021,6 +5042,9 @@ function getStealthScript(profile) {
5021
5042
 
5022
5043
  CanvasRenderingContext2D.prototype.getImageData = function(x, y, w, h) {
5023
5044
  const imageData = _getImageData.apply(this, arguments);
5045
+ if (isCaptchaCanvas(this.canvas)) {
5046
+ return imageData;
5047
+ }
5024
5048
  const data = imageData.data;
5025
5049
  const maxPixels = Math.min(data.length / 4, 2500);
5026
5050
  for (let i = 0; i < maxPixels * 4; i += 4) {
@@ -5944,8 +5968,9 @@ async function loginToQwen(accountId, email, password) {
5944
5968
  }
5945
5969
  if (attempt < maxAttempts) {
5946
5970
  const backoffMs = attempt * 5e3;
5971
+ const failReason = uiResult.reason || apiResult.reason || "falha tempor\xE1ria";
5947
5972
  console.warn(
5948
- `\u26A0\uFE0F [Playwright] Login attempt ${attempt}/${maxAttempts} failed for ${maskEmail(email)} (${apiResult.reason || uiResult.reason || "falha tempor\xE1ria"}), retrying in ${backoffMs / 1e3}s`
5973
+ `\u26A0\uFE0F [Playwright] Login attempt ${attempt}/${maxAttempts} failed for ${maskEmail(email)} (${failReason}), retrying in ${backoffMs / 1e3}s`
5949
5974
  );
5950
5975
  await sleep2(backoffMs);
5951
5976
  }
@@ -5975,37 +6000,52 @@ async function loginToQwen(accountId, email, password) {
5975
6000
  async function loginViaApi(page, email, password) {
5976
6001
  try {
5977
6002
  const hashedPassword = crypto5.createHash("sha256").update(password).digest("hex");
5978
- const signinUrl = qwenUrl("/api/v2/auths/signin");
5979
- let signinSuccess = false;
5980
- let data = null;
5981
- if (page.request && typeof page.request.post === "function") {
5982
- try {
5983
- const response = await page.request.post(signinUrl, {
5984
- data: {
5985
- email,
5986
- password: hashedPassword,
5987
- login_type: "email"
5988
- },
5989
- headers: {
5990
- "content-type": "application/json",
5991
- accept: "application/json, text/plain, */*",
5992
- referer: qwenUrl("/auth"),
5993
- origin: qwenOrigin(),
5994
- source: "web"
5995
- },
5996
- timeout: 1e4
5997
- });
5998
- data = await response.json().catch(() => null);
5999
- signinSuccess = Boolean(data && (data.success === true || data.token));
6000
- } catch {
6001
- }
6003
+ if (!page.url().includes("/auth")) {
6004
+ await page.goto(qwenUrl("/auth"), {
6005
+ waitUntil: "domcontentloaded",
6006
+ timeout: config.timeouts.navigation
6007
+ }).catch(() => {
6008
+ });
6009
+ await sleep2(1e3);
6002
6010
  }
6003
- if (!signinSuccess && !data) {
6004
- const requestId = crypto5.randomUUID();
6005
- const evalRes = await page.evaluate(
6006
- async ({ email: email2, password: password2, signinUrl: signinUrl2, requestId: requestId2 }) => {
6011
+ const signinUrl = "https://auth.qwen.ai/api/v2/auths/signin";
6012
+ const requestId = crypto5.randomUUID();
6013
+ const evalRes = await page.evaluate(
6014
+ async ({ email: email2, password: password2, signinUrl: signinUrl2, requestId: requestId2 }) => {
6015
+ try {
6016
+ const response = await fetch(signinUrl2, {
6017
+ method: "POST",
6018
+ signal: AbortSignal.timeout(15e3),
6019
+ credentials: "include",
6020
+ headers: {
6021
+ accept: "application/json, text/plain, */*",
6022
+ "content-type": "application/json",
6023
+ source: "web",
6024
+ version: "0.3.11",
6025
+ "x-request-origin": "https://chat.qwen.ai",
6026
+ timezone: (/* @__PURE__ */ new Date()).toString().split(" (")[0],
6027
+ "x-request-id": requestId2
6028
+ },
6029
+ body: JSON.stringify({ email: email2, password: password2 })
6030
+ });
6031
+ const json = await response.json().catch(() => null);
6032
+ return { ok: response.ok, status: response.status, data: json };
6033
+ } catch (e) {
6034
+ return { ok: false, error: e.message };
6035
+ }
6036
+ },
6037
+ { email, password: hashedPassword, signinUrl, requestId }
6038
+ ).catch(() => null);
6039
+ let data = evalRes?.data;
6040
+ let signinSuccess = Boolean(
6041
+ data && (data.success === true || data.token || data.data?.access_token || data.data?.token)
6042
+ );
6043
+ if (!signinSuccess && !data?.data?.code) {
6044
+ const fallbackUrl = qwenUrl("/api/v2/auths/signin");
6045
+ const fallbackRes = await page.evaluate(
6046
+ async ({ email: email2, password: password2, fallbackUrl: fallbackUrl2, requestId: requestId2 }) => {
6007
6047
  try {
6008
- const response = await fetch(signinUrl2, {
6048
+ const response = await fetch(fallbackUrl2, {
6009
6049
  method: "POST",
6010
6050
  signal: AbortSignal.timeout(1e4),
6011
6051
  credentials: "include",
@@ -6013,10 +6053,11 @@ async function loginViaApi(page, email, password) {
6013
6053
  accept: "application/json, text/plain, */*",
6014
6054
  "content-type": "application/json",
6015
6055
  source: "web",
6056
+ version: "0.3.11",
6016
6057
  timezone: (/* @__PURE__ */ new Date()).toString().split(" (")[0],
6017
6058
  "x-request-id": requestId2
6018
6059
  },
6019
- body: JSON.stringify({ email: email2, password: password2, login_type: "email" })
6060
+ body: JSON.stringify({ email: email2, password: password2 })
6020
6061
  });
6021
6062
  const json = await response.json().catch(() => null);
6022
6063
  return { ok: response.ok, status: response.status, data: json };
@@ -6024,11 +6065,13 @@ async function loginViaApi(page, email, password) {
6024
6065
  return { ok: false, error: e.message };
6025
6066
  }
6026
6067
  },
6027
- { email, password: hashedPassword, signinUrl, requestId }
6068
+ { email, password: hashedPassword, fallbackUrl, requestId }
6028
6069
  ).catch(() => null);
6029
- if (evalRes?.data) {
6030
- data = evalRes.data;
6031
- signinSuccess = Boolean(data && (data.success === true || data.token));
6070
+ if (fallbackRes?.data) {
6071
+ data = fallbackRes.data;
6072
+ signinSuccess = Boolean(
6073
+ data && (data.success === true || data.token || data.data?.access_token || data.data?.token)
6074
+ );
6032
6075
  }
6033
6076
  }
6034
6077
  if (data?.success === false) {
@@ -6042,7 +6085,8 @@ async function loginViaApi(page, email, password) {
6042
6085
  };
6043
6086
  }
6044
6087
  if (signinSuccess) {
6045
- const token = data?.data?.token || data?.token;
6088
+ const token = data?.data?.access_token || data?.data?.token || data?.access_token || data?.token;
6089
+ const refreshToken = data?.data?.refresh_token || data?.refresh_token;
6046
6090
  if (token) {
6047
6091
  try {
6048
6092
  await page.context().addCookies([
@@ -6066,14 +6110,19 @@ async function loginViaApi(page, email, password) {
6066
6110
  }).catch(() => {
6067
6111
  });
6068
6112
  if (token) {
6069
- await page.evaluate((tok) => {
6070
- try {
6071
- localStorage.removeItem("qwen_token_logged_out_marker");
6072
- localStorage.setItem("token", tok);
6073
- document.cookie = `token=${encodeURIComponent(tok)}; path=/; domain=.qwen.ai; max-age=31536000`;
6074
- } catch {
6075
- }
6076
- }, token).catch(() => {
6113
+ await page.evaluate(
6114
+ ({ tok, rTok }) => {
6115
+ try {
6116
+ localStorage.removeItem("qwen_token_logged_out_marker");
6117
+ localStorage.setItem("token", tok);
6118
+ localStorage.setItem("access_token", tok);
6119
+ if (rTok) localStorage.setItem("refresh_token", rTok);
6120
+ document.cookie = `token=${encodeURIComponent(tok)}; path=/; domain=.qwen.ai; max-age=31536000`;
6121
+ } catch {
6122
+ }
6123
+ },
6124
+ { tok: token, rTok: refreshToken }
6125
+ ).catch(() => {
6077
6126
  });
6078
6127
  await page.reload({ waitUntil: "domcontentloaded" }).catch(() => {
6079
6128
  });
@@ -6101,11 +6150,23 @@ async function loginViaApi(page, email, password) {
6101
6150
  }
6102
6151
  async function loginViaUi(page, email, password) {
6103
6152
  try {
6104
- await page.goto(qwenUrl("/auth"), {
6105
- waitUntil: "domcontentloaded",
6106
- timeout: config.timeouts.navigation
6107
- });
6108
- await sleep2(1500);
6153
+ if (!page.url().includes("/auth") && await isPageLoggedIn(page, 2e3).catch(() => false)) {
6154
+ return { success: true };
6155
+ }
6156
+ try {
6157
+ await page.goto(qwenUrl("/auth"), {
6158
+ waitUntil: "domcontentloaded",
6159
+ timeout: Math.min(config.timeouts.navigation, 15e3)
6160
+ });
6161
+ await sleep2(1e3);
6162
+ } catch (gotoErr) {
6163
+ if (!page.url().includes("/auth") && await isPageLoggedIn(page, 3e3).catch(() => false)) {
6164
+ return { success: true };
6165
+ }
6166
+ }
6167
+ if (!page.url().includes("/auth") && await isPageLoggedIn(page, 3e3).catch(() => false)) {
6168
+ return { success: true };
6169
+ }
6109
6170
  const emailSelector = [
6110
6171
  'input[type="email"]',
6111
6172
  'input[name="email"]',
@@ -6115,7 +6176,7 @@ async function loginViaUi(page, email, password) {
6115
6176
  ].join(", ");
6116
6177
  try {
6117
6178
  await page.waitForSelector(emailSelector, {
6118
- timeout: Math.min(config.timeouts.page, 8e3)
6179
+ timeout: Math.min(config.timeouts.page, 5e3)
6119
6180
  });
6120
6181
  } catch {
6121
6182
  if (!page.url().includes("/auth") && await isPageLoggedIn(page, 3e3)) {
@@ -6128,30 +6189,55 @@ async function loginViaUi(page, email, password) {
6128
6189
  return { success: false, reason: "Campo de e-mail n\xE3o encontrado (poss\xEDvel captcha)" };
6129
6190
  }
6130
6191
  await clearVisibleChallenge(page);
6131
- const findPasswordModeButton = () => {
6132
- return page.locator('button, [role="button"], a, div').filter({
6133
- hasText: /(?:log\s*in\s*with\s*(?:a\s*)?password|fazer\s*login\s*com\s*senha|entrar\s*com\s*(?:uma\s*)?senha|iniciar\s*sesi[oó]n\s*con\s*contrase[nñ]a|密码登录)/i
6134
- }).first();
6192
+ const isPasswordInputPresent = async () => {
6193
+ return await page.locator('input[type="password"], input[name="password"]').count().catch(() => 0) > 0;
6135
6194
  };
6136
- try {
6137
- const pwdModeBtn = findPasswordModeButton();
6138
- if (await pwdModeBtn.isVisible({ timeout: 2e3 }).catch(() => false)) {
6139
- await pwdModeBtn.click({ timeout: 2e3 }).catch(() => {
6195
+ const revealPasswordMode = async () => {
6196
+ if (page.url().includes("/forget")) {
6197
+ await page.goto(qwenUrl("/auth"), { waitUntil: "domcontentloaded", timeout: 1e4 }).catch(() => {
6140
6198
  });
6141
- await sleep2(500);
6199
+ await sleep2(1e3);
6142
6200
  }
6143
- } catch {
6144
- }
6145
- await page.fill(emailSelector, email);
6146
- await sleep2(300);
6147
- try {
6148
- const pwdModeBtn = findPasswordModeButton();
6149
- if (await pwdModeBtn.isVisible({ timeout: 1500 }).catch(() => false)) {
6150
- await pwdModeBtn.click({ timeout: 2e3 }).catch(() => {
6201
+ if (await isPasswordInputPresent()) return;
6202
+ const btn = page.locator("button").filter({
6203
+ hasText: /(?:log\s*in\s*with\s*(?:a\s*)?password|fazer\s*login\s*com\s*senha|entrar\s*com\s*(?:uma\s*)?senha|iniciar\s*sesi[oó]n\s*con\s*contrase[nñ]a|密码登录)/i
6204
+ }).filter({
6205
+ hasNotText: /(?:esqueci|forgot|olvid|reset|recover)/i
6206
+ }).first();
6207
+ if (await btn.isVisible({ timeout: 1500 }).catch(() => false)) {
6208
+ await btn.click({ timeout: 2e3 }).catch(() => {
6151
6209
  });
6152
6210
  await sleep2(500);
6153
6211
  }
6212
+ if (await isPasswordInputPresent()) return;
6213
+ await page.evaluate(() => {
6214
+ try {
6215
+ const buttons = Array.from(document.querySelectorAll("button, [role='button'], a"));
6216
+ for (const b of buttons) {
6217
+ const txt = (b.innerText || "").trim().toLowerCase();
6218
+ if (/(?:log\s*in\s*with\s*(?:a\s*)?password|fazer\s*login\s*com\s*senha|entrar\s*com\s*(?:uma\s*)?senha|iniciar\s*sesi[oó]n\s*con\s*contrase[nñ]a|密码登录)/i.test(txt) && !txt.includes("esqueci") && !txt.includes("forgot") && !txt.includes("olvid") && !txt.includes("reset")) {
6219
+ b.click();
6220
+ return true;
6221
+ }
6222
+ }
6223
+ } catch {
6224
+ }
6225
+ return false;
6226
+ }).catch(() => false);
6227
+ await sleep2(500);
6228
+ };
6229
+ await revealPasswordMode();
6230
+ try {
6231
+ await page.fill(emailSelector, email, { timeout: 8e3 });
6232
+ await sleep2(300);
6154
6233
  } catch {
6234
+ if (!page.url().includes("/auth") && await isPageLoggedIn(page, 3e3)) {
6235
+ return { success: true };
6236
+ }
6237
+ throw new Error(`Campo de e-mail n\xE3o encontrado na tela de autentica\xE7\xE3o`);
6238
+ }
6239
+ if (!await isPasswordInputPresent()) {
6240
+ await revealPasswordMode();
6155
6241
  }
6156
6242
  const passwordSelector = 'input[type="password"], input[name="password"]';
6157
6243
  try {
@@ -6170,61 +6256,108 @@ async function loginViaUi(page, email, password) {
6170
6256
  reason: "Campo de senha n\xE3o encontrado na tela de autentica\xE7\xE3o"
6171
6257
  };
6172
6258
  }
6173
- await page.fill(passwordSelector, password);
6174
- await sleep2(500);
6259
+ try {
6260
+ await page.fill(passwordSelector, password, { timeout: 8e3 });
6261
+ await sleep2(500);
6262
+ } catch {
6263
+ if (!page.url().includes("/auth") && await isPageLoggedIn(page, 3e3)) {
6264
+ return { success: true };
6265
+ }
6266
+ throw new Error(`Campo de senha n\xE3o encontrado na tela de autentica\xE7\xE3o`);
6267
+ }
6268
+ await page.evaluate(() => {
6269
+ try {
6270
+ const emailEl = document.querySelector('input[name="email"], input[type="email"], input[type="text"]');
6271
+ const passEl = document.querySelector('input[type="password"], input[name="password"]');
6272
+ if (emailEl) {
6273
+ emailEl.dispatchEvent(new Event("input", { bubbles: true }));
6274
+ emailEl.dispatchEvent(new Event("change", { bubbles: true }));
6275
+ emailEl.dispatchEvent(new Event("blur", { bubbles: true }));
6276
+ }
6277
+ if (passEl) {
6278
+ passEl.dispatchEvent(new Event("input", { bubbles: true }));
6279
+ passEl.dispatchEvent(new Event("change", { bubbles: true }));
6280
+ passEl.dispatchEvent(new Event("blur", { bubbles: true }));
6281
+ }
6282
+ } catch {
6283
+ }
6284
+ }).catch(() => {
6285
+ });
6175
6286
  const submitSelector = 'button.qwenchat-auth-pc-submit-button, button[type="submit"], button:has-text("Log in"), button:has-text("Sign in"), button:has-text("Fazer login"), button:has-text("Entrar"), button:has-text("Iniciar sesi\xF3n"), button:has-text("\u767B\u5F55")';
6176
6287
  const submitButton = page.locator(submitSelector).first();
6177
6288
  try {
6178
6289
  await page.waitForSelector('button[type="submit"]:not([disabled])', {
6179
- timeout: 5e3
6290
+ timeout: 4e3
6180
6291
  });
6181
6292
  await submitButton.click();
6182
6293
  } catch {
6183
- await page.keyboard.press("Enter");
6184
- }
6185
- await sleep2(3e3);
6186
- await solveBaxiaCaptcha(page, {
6187
- waitForMs: 2e3,
6188
- maxAttempts: config.captcha.maxAttempts,
6189
- retryDelayMs: config.captcha.retryDelayMs
6190
- }).catch(() => {
6191
- });
6192
- const codeSelector = 'input[placeholder*="code" i], input[placeholder*="c\xF3digo" i], input[name*="code" i]';
6193
- const codeInput = page.locator(codeSelector).first();
6194
- if (await codeInput.isVisible().catch(() => false)) {
6195
- return {
6196
- success: false,
6197
- reason: "Conta requer c\xF3digo de verifica\xE7\xE3o enviado por e-mail (2FA/OTP)"
6198
- };
6294
+ const isDisabled = await submitButton.isDisabled().catch(() => true);
6295
+ if (!isDisabled) {
6296
+ await submitButton.click({ force: true }).catch(() => {
6297
+ });
6298
+ } else {
6299
+ if (!page.url().includes("/auth") && await isPageLoggedIn(page, 2e3)) {
6300
+ return { success: true };
6301
+ }
6302
+ }
6199
6303
  }
6200
- const errorSelector = [
6201
- ".qwen-chat-v2-toast-text",
6202
- ".qwen-chat-v2-toast-content",
6203
- ".ant-form-item-explain-error",
6204
- ".ant-message-error",
6205
- ".ant-message-notice",
6206
- '[role="alert"]',
6207
- ".qwenchat-auth-error",
6208
- ".auth-error-message"
6209
- ].join(", ");
6210
- const errorEl = page.locator(errorSelector).first();
6211
- if (await errorEl.isVisible().catch(() => false)) {
6212
- const errorText = (await errorEl.innerText().catch(() => "")).trim();
6213
- if (errorText) {
6214
- const classified = classifyQwenAuthError(void 0, errorText);
6304
+ const postSubmitDeadline = Date.now() + 15e3;
6305
+ while (Date.now() < postSubmitDeadline) {
6306
+ if (page.isClosed()) break;
6307
+ if (config.captcha.enabled) {
6308
+ await solveBaxiaCaptcha(page, {
6309
+ waitForMs: 1500,
6310
+ maxAttempts: config.captcha.maxAttempts,
6311
+ retryDelayMs: config.captcha.retryDelayMs
6312
+ }).catch(() => {
6313
+ });
6314
+ }
6315
+ const errorSelector = [
6316
+ ".qwen-chat-v2-toast-text",
6317
+ ".qwen-chat-v2-toast-content",
6318
+ ".ant-form-item-explain-error",
6319
+ ".ant-message-error",
6320
+ ".ant-message-notice",
6321
+ '[role="alert"]',
6322
+ ".qwenchat-auth-error",
6323
+ ".auth-error-message"
6324
+ ].join(", ");
6325
+ const errorEl = page.locator(errorSelector).first();
6326
+ if (await errorEl.isVisible().catch(() => false)) {
6327
+ const errorText = (await errorEl.innerText().catch(() => "")).trim();
6328
+ if (errorText) {
6329
+ const classified = classifyQwenAuthError(void 0, errorText);
6330
+ return {
6331
+ success: false,
6332
+ permanentFailure: classified.isPermanent,
6333
+ reason: `Formul\xE1rio: ${classified.reason}`
6334
+ };
6335
+ }
6336
+ }
6337
+ const codeSelector = 'input[placeholder*="code" i], input[placeholder*="c\xF3digo" i], input[name*="code" i]';
6338
+ const codeInput = page.locator(codeSelector).first();
6339
+ if (await codeInput.isVisible().catch(() => false)) {
6215
6340
  return {
6216
6341
  success: false,
6217
- permanentFailure: classified.isPermanent,
6218
- reason: `Formul\xE1rio: ${classified.reason}`
6342
+ reason: "Conta requer c\xF3digo de verifica\xE7\xE3o enviado por e-mail (2FA/OTP)"
6219
6343
  };
6220
6344
  }
6345
+ try {
6346
+ const liveCookies = await page.context().cookies();
6347
+ if (liveCookies.some((c) => c.name === "token")) {
6348
+ return { success: true };
6349
+ }
6350
+ } catch {
6351
+ }
6352
+ const currentUrl = page.url();
6353
+ if (!currentUrl.includes("/auth") && !currentUrl.includes("/login")) {
6354
+ if (await isPageLoggedIn(page, 3e3)) {
6355
+ return { success: true };
6356
+ }
6357
+ }
6358
+ await sleep2(1e3);
6221
6359
  }
6222
- const isLoggedIn = await isPageLoggedIn(page);
6223
- if (isLoggedIn) {
6224
- await page.goto(qwenUrl("/"), {
6225
- waitUntil: "domcontentloaded",
6226
- timeout: config.timeouts.navigation
6227
- });
6360
+ if (await isPageLoggedIn(page, 3e3)) {
6228
6361
  return { success: true };
6229
6362
  }
6230
6363
  return {
@@ -6752,6 +6885,17 @@ async function refreshHeadersInternal(accountId, timeoutMs = config.timeouts.hea
6752
6885
  }
6753
6886
  };
6754
6887
  if (forceReauth) {
6888
+ const alreadyIn = await isPageLoggedIn(page, 2e3).catch(() => false);
6889
+ if (alreadyIn) {
6890
+ const liveCookies = await page.context().cookies();
6891
+ if (liveCookies.some((c) => c.name === "token")) {
6892
+ const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
6893
+ cache3.headers.cookie = cookieStr;
6894
+ cache3.lastRefresh = Date.now();
6895
+ markAccountHeadersReady(accountId);
6896
+ return;
6897
+ }
6898
+ }
6755
6899
  await executeReauth();
6756
6900
  } else {
6757
6901
  try {
@@ -7186,19 +7330,50 @@ async function keepAlivePlaywrightAccount(accountId) {
7186
7330
  const now = Date.now();
7187
7331
  const currentUrl = page.url();
7188
7332
  const cookie = await getCookies(accountId);
7189
- if (cookie && isTokenExpiringSoon(cookie, 45)) {
7190
- console.log(
7191
- `\u{1F493} [SessionKeeper] Account ${accountId} token expires within 45m; proactively renewing session...`
7192
- );
7333
+ if (cookie && isTokenExpiringSoon(cookie, 2)) {
7193
7334
  try {
7194
- await refreshHeadersInternal(accountId, config.timeouts.headers, true);
7195
- lastKeepAliveNavigation.set(accountId, now);
7196
- touchAccountActivity(accountId);
7197
- return true;
7198
- } catch (err) {
7199
- console.warn(
7200
- `[SessionKeeper] Proactive session renewal failed for ${accountId}: ${getErrorMessage(err)}`
7335
+ await page.evaluate(async () => {
7336
+ await fetch("https://auth.qwen.ai/api/v2/auths/refresh", {
7337
+ method: "GET",
7338
+ credentials: "include"
7339
+ }).catch(() => {
7340
+ });
7341
+ await fetch("/api/v1/auths/", {
7342
+ method: "GET",
7343
+ credentials: "include"
7344
+ }).catch(() => {
7345
+ });
7346
+ }).catch(() => {
7347
+ });
7348
+ const liveCookies = await page.context().cookies();
7349
+ const tokenCookie = liveCookies.find((c) => c.name === "token");
7350
+ if (tokenCookie) {
7351
+ const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
7352
+ const cache3 = getHeaderCache(accountId);
7353
+ cache3.headers.cookie = cookieStr;
7354
+ cache3.lastRefresh = Date.now();
7355
+ markAccountHeadersReady(accountId);
7356
+ lastKeepAliveNavigation.set(accountId, now);
7357
+ touchAccountActivity(accountId);
7358
+ return true;
7359
+ }
7360
+ } catch {
7361
+ }
7362
+ const loggedIn = await isPageLoggedIn(page, 2e3).catch(() => false);
7363
+ if (!loggedIn) {
7364
+ console.log(
7365
+ `\u{1F493} [SessionKeeper] Account ${accountId} session expired; renewing session...`
7201
7366
  );
7367
+ try {
7368
+ await refreshHeadersInternal(accountId, config.timeouts.headers, true);
7369
+ lastKeepAliveNavigation.set(accountId, now);
7370
+ touchAccountActivity(accountId);
7371
+ return true;
7372
+ } catch (err) {
7373
+ console.warn(
7374
+ `[SessionKeeper] Proactive session renewal failed for ${accountId}: ${getErrorMessage(err)}`
7375
+ );
7376
+ }
7202
7377
  }
7203
7378
  }
7204
7379
  const lastNavigation = lastKeepAliveNavigation.get(accountId) ?? 0;
@@ -25498,7 +25673,7 @@ function getAppVersion() {
25498
25673
  }
25499
25674
  } catch {
25500
25675
  }
25501
- cachedVersion = "v1.4.2";
25676
+ cachedVersion = "v1.4.7";
25502
25677
  return cachedVersion;
25503
25678
  }
25504
25679
  var cachedVersion;