qwenproxy-cli 1.6.9 → 1.6.10

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/login.js CHANGED
@@ -3492,7 +3492,19 @@ async function isPageLoggedIn(page, timeoutMs = SESSION_PROBE_NAVIGATION_TIMEOUT
3492
3492
  if (localStorage.getItem("qwen_token_logged_out_marker")) {
3493
3493
  return false;
3494
3494
  }
3495
- const res = await fetch("/api/v1/auths/", { method: "GET" });
3495
+ const lsToken = (localStorage.getItem("token") || "").trim();
3496
+ if (lsToken && !/(?:^|;\s*)token=/.test(document.cookie || "")) {
3497
+ try {
3498
+ document.cookie = `token=${encodeURIComponent(lsToken)}; path=/; domain=.qwen.ai; max-age=31536000`;
3499
+ } catch {
3500
+ }
3501
+ }
3502
+ const authHeaders = lsToken ? { Authorization: `Bearer ${lsToken}` } : {};
3503
+ const res = await fetch("/api/v1/auths/", {
3504
+ method: "GET",
3505
+ headers: authHeaders,
3506
+ credentials: "include"
3507
+ });
3496
3508
  if (res.status !== 200) return false;
3497
3509
  const json = await res.json().catch(() => null);
3498
3510
  if (!json) return false;
@@ -3510,6 +3522,7 @@ async function isPageLoggedIn(page, timeoutMs = SESSION_PROBE_NAVIGATION_TIMEOUT
3510
3522
  try {
3511
3523
  const settingsRes = await fetch("/api/v2/users/user/settings", {
3512
3524
  method: "GET",
3525
+ headers: authHeaders,
3513
3526
  credentials: "include",
3514
3527
  signal: AbortSignal.timeout(3e3)
3515
3528
  });
@@ -4668,8 +4681,15 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
4668
4681
  const hasAuthCookie = cookies.some(
4669
4682
  (c) => c.name.toLowerCase().includes("token") || c.name.toLowerCase().includes("session")
4670
4683
  );
4684
+ let initialLoginAttempted = false;
4671
4685
  if (!hasAuthCookie && account.email && account.password) {
4672
- await loginToQwen(account.id, account.email, account.password);
4686
+ initialLoginAttempted = true;
4687
+ const loggedIn = await loginToQwen(account.id, account.email, account.password);
4688
+ if (!loggedIn) {
4689
+ throw new Error(
4690
+ `Authentication failed for account ${maskEmail(account.email)}`
4691
+ );
4692
+ }
4673
4693
  }
4674
4694
  try {
4675
4695
  await acctPage.goto(qwenUrl("/"), {
@@ -4679,13 +4699,21 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
4679
4699
  await sleep2(1500);
4680
4700
  const currentUrl = acctPage.url();
4681
4701
  const isAuthUrl = currentUrl.includes("/auth") || currentUrl.includes("/login");
4682
- if (isAuthUrl && account.email && account.password) {
4702
+ if (isAuthUrl && !initialLoginAttempted && account.email && account.password) {
4683
4703
  console.log(
4684
4704
  `[Playwright] Initial login needed for ${maskEmail(account.email)}, authenticating...`
4685
4705
  );
4686
- await loginToQwen(account.id, account.email, account.password);
4706
+ const loggedIn = await loginToQwen(account.id, account.email, account.password);
4707
+ if (!loggedIn) {
4708
+ throw new Error(
4709
+ `Authentication failed for account ${maskEmail(account.email)}`
4710
+ );
4711
+ }
4687
4712
  }
4688
4713
  } catch (err) {
4714
+ if (err?.message?.includes("Authentication failed for account")) {
4715
+ throw err;
4716
+ }
4689
4717
  console.warn(
4690
4718
  `\u26A0\uFE0F [Playwright] Initial navigation check for ${maskEmail(account.email)}: ${err.message}`
4691
4719
  );
@@ -5234,10 +5262,30 @@ async function loginToQwen(accountId, email, password) {
5234
5262
  const uiResult = await loginViaUi(page, email, password);
5235
5263
  if (uiResult.success) {
5236
5264
  cookieCaches.delete(accountId);
5237
- await saveStorageState(page.context(), accountId);
5238
5265
  try {
5239
- const liveCookies = await page.context().cookies();
5240
- const tokenCookie = liveCookies.find((c) => c.name === "token");
5266
+ let liveCookies = await page.context().cookies();
5267
+ let tokenCookie = liveCookies.find((c) => c.name === "token");
5268
+ if (!tokenCookie) {
5269
+ const lsTok = uiResult.token || await page.evaluate(() => (localStorage.getItem("token") || "").trim()).catch(() => "");
5270
+ if (lsTok) {
5271
+ await page.context().addCookies([
5272
+ {
5273
+ name: "token",
5274
+ value: lsTok,
5275
+ domain: ".qwen.ai",
5276
+ path: "/",
5277
+ expires: Math.floor(Date.now() / 1e3) + 31536e3,
5278
+ httpOnly: false,
5279
+ secure: true,
5280
+ sameSite: "Lax"
5281
+ }
5282
+ ]).catch(() => {
5283
+ });
5284
+ liveCookies = await page.context().cookies();
5285
+ tokenCookie = liveCookies.find((c) => c.name === "token");
5286
+ }
5287
+ }
5288
+ await saveStorageState(page.context(), accountId);
5241
5289
  if (tokenCookie) {
5242
5290
  const cookieStr = liveCookies.map((c) => `${c.name}=${c.value}`).join("; ");
5243
5291
  const cache = getHeaderCache(accountId);
@@ -5246,7 +5294,7 @@ async function loginToQwen(accountId, email, password) {
5246
5294
  markAccountHeadersReady(accountId);
5247
5295
  const { saveAuthSession: saveAuthSession2 } = await Promise.resolve().then(() => (init_database(), database_exports));
5248
5296
  const exp = parseJwtExpiry(tokenCookie.value);
5249
- let rTok = uiResult.refreshToken;
5297
+ let rTok = uiResult.refreshToken || liveCookies.find((c) => c.name === "refresh_token")?.value;
5250
5298
  if (!rTok) {
5251
5299
  try {
5252
5300
  rTok = await page.evaluate(() => localStorage.getItem("refresh_token") || "") || void 0;
@@ -5327,8 +5375,9 @@ async function loginViaApi(page, email, password) {
5327
5375
  }
5328
5376
  const signinUrl = "https://auth.qwen.ai/api/v2/auths/signin";
5329
5377
  const requestId = crypto3.randomUUID();
5378
+ const webVersion = getQwenWebVersion() || "0.3.26";
5330
5379
  const evalRes = await page.evaluate(
5331
- async ({ email: email2, password: password2, signinUrl: signinUrl2, requestId: requestId2, tz }) => {
5380
+ async ({ email: email2, password: password2, signinUrl: signinUrl2, requestId: requestId2, tz, version }) => {
5332
5381
  try {
5333
5382
  const response = await fetch(signinUrl2, {
5334
5383
  method: "POST",
@@ -5338,7 +5387,7 @@ async function loginViaApi(page, email, password) {
5338
5387
  accept: "application/json, text/plain, */*",
5339
5388
  "content-type": "application/json",
5340
5389
  source: "web",
5341
- version: getQwenWebVersion() || "0.3.26",
5390
+ version,
5342
5391
  "x-request-origin": "https://chat.qwen.ai",
5343
5392
  timezone: tz,
5344
5393
  "x-request-id": requestId2
@@ -5351,7 +5400,14 @@ async function loginViaApi(page, email, password) {
5351
5400
  return { ok: false, error: e.message };
5352
5401
  }
5353
5402
  },
5354
- { email, password: hashedPassword, signinUrl, requestId, tz: formatAsciiTimezone() }
5403
+ {
5404
+ email,
5405
+ password: hashedPassword,
5406
+ signinUrl,
5407
+ requestId,
5408
+ tz: formatAsciiTimezone(),
5409
+ version: webVersion
5410
+ }
5355
5411
  ).catch(() => null);
5356
5412
  let data = evalRes?.data;
5357
5413
  let signinSuccess = Boolean(
@@ -5360,7 +5416,7 @@ async function loginViaApi(page, email, password) {
5360
5416
  if (!signinSuccess && !data?.data?.code) {
5361
5417
  const fallbackUrl = qwenUrl("/api/v2/auths/signin");
5362
5418
  const fallbackRes = await page.evaluate(
5363
- async ({ email: email2, password: password2, fallbackUrl: fallbackUrl2, requestId: requestId2, tz }) => {
5419
+ async ({ email: email2, password: password2, fallbackUrl: fallbackUrl2, requestId: requestId2, tz, version }) => {
5364
5420
  try {
5365
5421
  const response = await fetch(fallbackUrl2, {
5366
5422
  method: "POST",
@@ -5370,7 +5426,7 @@ async function loginViaApi(page, email, password) {
5370
5426
  accept: "application/json, text/plain, */*",
5371
5427
  "content-type": "application/json",
5372
5428
  source: "web",
5373
- version: getQwenWebVersion() || "0.3.26",
5429
+ version,
5374
5430
  timezone: tz,
5375
5431
  "x-request-id": requestId2
5376
5432
  },
@@ -5382,7 +5438,14 @@ async function loginViaApi(page, email, password) {
5382
5438
  return { ok: false, error: e.message };
5383
5439
  }
5384
5440
  },
5385
- { email, password: hashedPassword, fallbackUrl, requestId, tz: formatAsciiTimezone() }
5441
+ {
5442
+ email,
5443
+ password: hashedPassword,
5444
+ fallbackUrl,
5445
+ requestId,
5446
+ tz: formatAsciiTimezone(),
5447
+ version: webVersion
5448
+ }
5386
5449
  ).catch(() => null);
5387
5450
  if (fallbackRes?.data) {
5388
5451
  data = fallbackRes.data;
@@ -5607,28 +5670,34 @@ async function loginViaUi(page, email, password) {
5607
5670
  await sleep2(500);
5608
5671
  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")';
5609
5672
  const submitButton = page.locator(submitSelector).first();
5610
- await page.evaluate((sel) => {
5611
- try {
5612
- const btn = document.querySelector(sel);
5613
- if (btn) {
5614
- btn.removeAttribute("disabled");
5615
- btn.classList.remove("ant-btn-disabled");
5616
- btn.click();
5617
- }
5618
- } catch {
5619
- }
5620
- }, submitSelector).catch(() => {
5621
- });
5673
+ let submitted = false;
5622
5674
  try {
5623
5675
  if (await submitButton.isVisible({ timeout: 2e3 }).catch(() => false)) {
5624
- await submitButton.click({ force: true, timeout: 2e3 }).catch(() => {
5676
+ await submitButton.click({ timeout: 2e3 }).catch(() => {
5625
5677
  });
5678
+ submitted = true;
5626
5679
  }
5627
5680
  } catch {
5628
5681
  }
5629
- const passInput = page.locator(passwordSelector).first();
5630
- await passInput.press("Enter", { timeout: 2e3 }).catch(() => {
5631
- });
5682
+ if (!submitted) {
5683
+ await page.evaluate(() => {
5684
+ try {
5685
+ const btn = document.querySelector(
5686
+ 'button.qwenchat-auth-pc-submit-button, button[type="submit"]'
5687
+ );
5688
+ if (btn) {
5689
+ btn.removeAttribute("disabled");
5690
+ btn.classList.remove("ant-btn-disabled");
5691
+ btn.click();
5692
+ }
5693
+ } catch {
5694
+ }
5695
+ }).catch(() => {
5696
+ });
5697
+ const passInput = page.locator(passwordSelector).first();
5698
+ await passInput.press("Enter", { timeout: 2e3 }).catch(() => {
5699
+ });
5700
+ }
5632
5701
  const postSubmitDeadline = Date.now() + 15e3;
5633
5702
  while (Date.now() < postSubmitDeadline) {
5634
5703
  if (page.isClosed()) break;
@@ -5646,9 +5715,12 @@ async function loginViaUi(page, email, password) {
5646
5715
  ".ant-form-item-explain-error",
5647
5716
  ".ant-message-error",
5648
5717
  ".ant-message-notice",
5718
+ ".ant-message-custom-content",
5719
+ ".ant-notification-notice",
5649
5720
  '[role="alert"]',
5650
5721
  ".qwenchat-auth-error",
5651
- ".auth-error-message"
5722
+ ".auth-error-message",
5723
+ ".qwenchat-toast"
5652
5724
  ].join(", ");
5653
5725
  const errorEl = page.locator(errorSelector).first();
5654
5726
  if (await errorEl.isVisible().catch(() => false)) {
@@ -5662,7 +5734,15 @@ async function loginViaUi(page, email, password) {
5662
5734
  };
5663
5735
  }
5664
5736
  }
5665
- const codeSelector = 'input[placeholder*="code" i], input[placeholder*="c\xF3digo" i], input[name*="code" i]';
5737
+ const codeSelector = [
5738
+ 'input[placeholder*="code" i]',
5739
+ 'input[placeholder*="c\xF3digo" i]',
5740
+ 'input[name*="code" i]',
5741
+ ".qwenchat-verification-code-input",
5742
+ ".qwenchat-verification-code-input-cell",
5743
+ '[aria-label*="Verification code" i]',
5744
+ '[aria-label*="c\xF3digo de verifica\xE7\xE3o" i]'
5745
+ ].join(", ");
5666
5746
  const codeInput = page.locator(codeSelector).first();
5667
5747
  if (await codeInput.isVisible().catch(() => false)) {
5668
5748
  return {
@@ -5672,16 +5752,44 @@ async function loginViaUi(page, email, password) {
5672
5752
  }
5673
5753
  try {
5674
5754
  const liveCookies = await page.context().cookies();
5675
- if (liveCookies.some((c) => c.name === "token")) {
5676
- return { success: true };
5755
+ const rTokCookie = liveCookies.find((c) => c.name === "refresh_token")?.value;
5756
+ const tokCookie = liveCookies.find((c) => c.name === "token")?.value;
5757
+ if (tokCookie) {
5758
+ return { success: true, token: tokCookie, refreshToken: rTokCookie };
5677
5759
  }
5678
- } catch {
5679
- }
5680
- const currentUrl = page.url();
5681
- if (!currentUrl.includes("/auth") && !currentUrl.includes("/login")) {
5682
- if (await isPageLoggedIn(page, 3e3)) {
5683
- return { success: true };
5760
+ const currentUrl = page.url();
5761
+ if (!currentUrl.includes("/auth") && !currentUrl.includes("/login")) {
5762
+ const lsTok = await page.evaluate(() => {
5763
+ const t = (localStorage.getItem("token") || "").trim();
5764
+ if (t) {
5765
+ try {
5766
+ document.cookie = `token=${encodeURIComponent(t)}; path=/; domain=.qwen.ai; max-age=31536000`;
5767
+ } catch {
5768
+ }
5769
+ }
5770
+ return t;
5771
+ }).catch(() => "");
5772
+ if (lsTok) {
5773
+ await page.context().addCookies([
5774
+ {
5775
+ name: "token",
5776
+ value: lsTok,
5777
+ domain: ".qwen.ai",
5778
+ path: "/",
5779
+ expires: Math.floor(Date.now() / 1e3) + 31536e3,
5780
+ httpOnly: false,
5781
+ secure: true,
5782
+ sameSite: "Lax"
5783
+ }
5784
+ ]).catch(() => {
5785
+ });
5786
+ return { success: true, token: lsTok, refreshToken: rTokCookie };
5787
+ }
5788
+ if (await isPageLoggedIn(page, 3e3)) {
5789
+ return { success: true, refreshToken: rTokCookie };
5790
+ }
5684
5791
  }
5792
+ } catch {
5685
5793
  }
5686
5794
  await sleep2(1e3);
5687
5795
  }
@@ -5711,10 +5819,18 @@ async function refreshAccountToken(accountId) {
5711
5819
  } catch {
5712
5820
  }
5713
5821
  }
5822
+ if (!refreshToken) {
5823
+ try {
5824
+ const liveCookies = await page.context().cookies();
5825
+ refreshToken = liveCookies.find((c) => c.name === "refresh_token")?.value;
5826
+ } catch {
5827
+ }
5828
+ }
5714
5829
  if (refreshToken) {
5715
5830
  try {
5831
+ const webVersion = getQwenWebVersion() || "0.3.26";
5716
5832
  const refreshResult = await page.evaluate(
5717
- async ({ rTok, tz }) => {
5833
+ async ({ rTok, tz, version }) => {
5718
5834
  try {
5719
5835
  const response = await fetch("https://auth.qwen.ai/api/v2/auths/refresh", {
5720
5836
  method: "GET",
@@ -5722,7 +5838,7 @@ async function refreshAccountToken(accountId) {
5722
5838
  headers: {
5723
5839
  accept: "application/json, text/plain, */*",
5724
5840
  source: "web",
5725
- version: getQwenWebVersion() || "0.3.26",
5841
+ version,
5726
5842
  "x-request-origin": "https://chat.qwen.ai",
5727
5843
  timezone: tz,
5728
5844
  authorization: `Bearer ${rTok}`
@@ -5734,7 +5850,7 @@ async function refreshAccountToken(accountId) {
5734
5850
  return { ok: false, error: e.message };
5735
5851
  }
5736
5852
  },
5737
- { rTok: refreshToken, tz: formatAsciiTimezone() }
5853
+ { rTok: refreshToken, tz: formatAsciiTimezone(), version: webVersion }
5738
5854
  );
5739
5855
  const json = refreshResult?.data;
5740
5856
  if (json && json.success === true && json.data) {