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/clean-cache.js +159 -43
- package/dist/delete-chats.js +159 -43
- package/dist/index.js +160 -44
- package/dist/login.js +159 -43
- package/dist/reset-cooldowns.js +159 -43
- package/package.json +1 -1
- package/src/core/version.ts +1 -1
- package/src/services/playwright.ts +171 -46
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
|
|
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
|
-
|
|
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
|
-
|
|
5240
|
-
|
|
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
|
|
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
|
-
{
|
|
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
|
|
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
|
-
{
|
|
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
|
-
|
|
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({
|
|
5676
|
+
await submitButton.click({ timeout: 2e3 }).catch(() => {
|
|
5625
5677
|
});
|
|
5678
|
+
submitted = true;
|
|
5626
5679
|
}
|
|
5627
5680
|
} catch {
|
|
5628
5681
|
}
|
|
5629
|
-
|
|
5630
|
-
|
|
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 =
|
|
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
|
-
|
|
5676
|
-
|
|
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
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
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
|
|
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) {
|