qwenproxy-cli 1.6.10 → 1.6.12
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 +390 -30
- package/dist/delete-chats.js +946 -445
- package/dist/index.js +612 -100
- package/dist/login.js +417 -51
- package/dist/reset-cooldowns.js +769 -407
- package/dist/sync-clients.js +4 -1
- package/package.json +2 -2
- package/src/api/server.ts +8 -4
- package/src/core/config.ts +4 -1
- package/src/core/model-alias.ts +1 -0
- package/src/core/version.ts +1 -1
- package/src/core/watchdog.ts +4 -3
- package/src/routes/chat/account.ts +12 -0
- package/src/routes/chat/streaming.ts +18 -2
- package/src/services/auth-playwright.ts +3 -2
- package/src/services/captcha-coordinator.ts +41 -11
- package/src/services/captcha-solver.ts +400 -2
- package/src/services/chat-cleanup.ts +11 -2
- package/src/services/playwright.ts +135 -50
- package/src/services/qwen-chat-pool.ts +52 -9
- package/src/services/qwen-headers.ts +18 -1
- package/src/services/qwen.ts +35 -7
- package/src/services/session-keeper.ts +70 -8
package/dist/login.js
CHANGED
|
@@ -1228,7 +1228,7 @@ var init_config = __esm({
|
|
|
1228
1228
|
// Version header on Qwen API requests = the deployed web bundle version
|
|
1229
1229
|
// (fallback when dynamic DOM detection is not yet completed).
|
|
1230
1230
|
// Override via env when Qwen ships a new bundle.
|
|
1231
|
-
QWEN_WEB_VERSION: z.string().default("0.3.
|
|
1231
|
+
QWEN_WEB_VERSION: z.string().default("0.3.43"),
|
|
1232
1232
|
// Controls bx-ua/bx-umidtoken injection on the GENERAL API paths
|
|
1233
1233
|
// (chats/new, settings): those work without them (live-probed). The
|
|
1234
1234
|
// completions path is the exception — the 0.2.86 HAR shows the real
|
|
@@ -1271,6 +1271,7 @@ var init_config = __esm({
|
|
|
1271
1271
|
CAPTCHA_SOLVER_ENABLED: z.string().default("true"),
|
|
1272
1272
|
CAPTCHA_SOLVER_MAX_ATTEMPTS: z.string().default("3"),
|
|
1273
1273
|
CAPTCHA_SOLVER_TIMEOUT_MS: z.string().default("15000"),
|
|
1274
|
+
CAPTCHA_SLIDER_TIMEOUT_MS: z.string().default("8000"),
|
|
1274
1275
|
CAPTCHA_SOLVER_RETRY_DELAY_MS: z.string().default("1000"),
|
|
1275
1276
|
CAPTCHA_SOLVER_SETTLE_MS: z.string().default("2000"),
|
|
1276
1277
|
CAPTCHA_ACCOUNT_COOLDOWN_MS: z.string().default("120000"),
|
|
@@ -1422,6 +1423,8 @@ var init_config = __esm({
|
|
|
1422
1423
|
enabled: env.CAPTCHA_SOLVER_ENABLED === "true",
|
|
1423
1424
|
maxAttempts: Math.max(1, Math.min(5, parseInt(env.CAPTCHA_SOLVER_MAX_ATTEMPTS))),
|
|
1424
1425
|
timeoutMs: Math.max(0, parseInt(env.CAPTCHA_SOLVER_TIMEOUT_MS)),
|
|
1426
|
+
/** Max wait for a challenge slider to become visible (slow WAF renders). */
|
|
1427
|
+
sliderTimeoutMs: Math.max(500, parseInt(env.CAPTCHA_SLIDER_TIMEOUT_MS)),
|
|
1425
1428
|
retryDelayMs: Math.max(0, parseInt(env.CAPTCHA_SOLVER_RETRY_DELAY_MS)),
|
|
1426
1429
|
settleMs: Math.max(0, parseInt(env.CAPTCHA_SOLVER_SETTLE_MS)),
|
|
1427
1430
|
/** Rest an account whose challenge could not be cleared before reusing it. */
|
|
@@ -2612,6 +2615,294 @@ function logBaxiaCaptcha(event, fields = {}, important = false) {
|
|
|
2612
2615
|
console.log(line);
|
|
2613
2616
|
}
|
|
2614
2617
|
}
|
|
2618
|
+
async function findVisibleLocatorWithin(page, selectors, timeoutMs) {
|
|
2619
|
+
const deadline = Date.now() + Math.max(0, timeoutMs);
|
|
2620
|
+
while (true) {
|
|
2621
|
+
const found = await findVisibleLocator(page, selectors);
|
|
2622
|
+
if (found) return found;
|
|
2623
|
+
if (Date.now() >= deadline) return null;
|
|
2624
|
+
await sleep(Math.min(150, Math.max(1, deadline - Date.now())));
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
async function waitForHidden(locator, timeoutMs) {
|
|
2628
|
+
const deadline = Date.now() + Math.max(0, timeoutMs);
|
|
2629
|
+
while (true) {
|
|
2630
|
+
if (!await isVisible(locator)) return true;
|
|
2631
|
+
if (Date.now() >= deadline) return false;
|
|
2632
|
+
await sleep(Math.min(100, Math.max(1, deadline - Date.now())));
|
|
2633
|
+
}
|
|
2634
|
+
}
|
|
2635
|
+
async function computeAliyunPuzzleOffset(page) {
|
|
2636
|
+
return page.evaluate(() => {
|
|
2637
|
+
const background = document.querySelector(
|
|
2638
|
+
"#aliyunCaptcha-img"
|
|
2639
|
+
);
|
|
2640
|
+
const piece = document.querySelector(
|
|
2641
|
+
"#aliyunCaptcha-puzzle"
|
|
2642
|
+
);
|
|
2643
|
+
if (!background || !piece) {
|
|
2644
|
+
return Promise.resolve({ ok: false, reason: "missing puzzle images" });
|
|
2645
|
+
}
|
|
2646
|
+
const compute = () => {
|
|
2647
|
+
try {
|
|
2648
|
+
const width = background.naturalWidth;
|
|
2649
|
+
const height = background.naturalHeight;
|
|
2650
|
+
const pieceWidth = piece.naturalWidth;
|
|
2651
|
+
const pieceHeight = piece.naturalHeight;
|
|
2652
|
+
if (!width || !height || !pieceWidth || !pieceHeight) {
|
|
2653
|
+
return { ok: false, reason: "image dimensions unavailable" };
|
|
2654
|
+
}
|
|
2655
|
+
const backgroundCanvas = document.createElement("canvas");
|
|
2656
|
+
backgroundCanvas.id = "captcha-solver-canvas";
|
|
2657
|
+
backgroundCanvas.width = width;
|
|
2658
|
+
backgroundCanvas.height = height;
|
|
2659
|
+
const backgroundContext = backgroundCanvas.getContext("2d");
|
|
2660
|
+
if (!backgroundContext) {
|
|
2661
|
+
return { ok: false, reason: "no background context" };
|
|
2662
|
+
}
|
|
2663
|
+
const pieceCanvas = document.createElement("canvas");
|
|
2664
|
+
pieceCanvas.id = "captcha-solver-canvas";
|
|
2665
|
+
pieceCanvas.width = pieceWidth;
|
|
2666
|
+
pieceCanvas.height = pieceHeight;
|
|
2667
|
+
const pieceContext = pieceCanvas.getContext("2d");
|
|
2668
|
+
if (!pieceContext) {
|
|
2669
|
+
return { ok: false, reason: "no piece context" };
|
|
2670
|
+
}
|
|
2671
|
+
try {
|
|
2672
|
+
backgroundContext.drawImage(background, 0, 0);
|
|
2673
|
+
} catch {
|
|
2674
|
+
return { ok: false, reason: "background canvas tainted" };
|
|
2675
|
+
}
|
|
2676
|
+
try {
|
|
2677
|
+
pieceContext.drawImage(piece, 0, 0);
|
|
2678
|
+
} catch {
|
|
2679
|
+
return { ok: false, reason: "puzzle canvas tainted" };
|
|
2680
|
+
}
|
|
2681
|
+
const backgroundData = backgroundContext.getImageData(
|
|
2682
|
+
0,
|
|
2683
|
+
0,
|
|
2684
|
+
width,
|
|
2685
|
+
height
|
|
2686
|
+
).data;
|
|
2687
|
+
const pieceData = pieceContext.getImageData(
|
|
2688
|
+
0,
|
|
2689
|
+
0,
|
|
2690
|
+
pieceWidth,
|
|
2691
|
+
pieceHeight
|
|
2692
|
+
).data;
|
|
2693
|
+
let pieceMinX = pieceWidth;
|
|
2694
|
+
let pieceMaxX = -1;
|
|
2695
|
+
let pieceMinY = pieceHeight;
|
|
2696
|
+
let pieceMaxY = -1;
|
|
2697
|
+
for (let y = 0; y < pieceHeight; y++) {
|
|
2698
|
+
for (let x = 0; x < pieceWidth; x++) {
|
|
2699
|
+
if (pieceData[(y * pieceWidth + x) * 4 + 3] > 100) {
|
|
2700
|
+
if (x < pieceMinX) pieceMinX = x;
|
|
2701
|
+
if (x > pieceMaxX) pieceMaxX = x;
|
|
2702
|
+
if (y < pieceMinY) pieceMinY = y;
|
|
2703
|
+
if (y > pieceMaxY) pieceMaxY = y;
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
const puzzleWidth = pieceMaxX - pieceMinX + 1;
|
|
2708
|
+
if (puzzleWidth <= 0) {
|
|
2709
|
+
return { ok: false, reason: "empty puzzle piece" };
|
|
2710
|
+
}
|
|
2711
|
+
const yStart = Math.max(1, Math.min(height - 2, pieceMinY + 5));
|
|
2712
|
+
const yEnd = Math.max(
|
|
2713
|
+
yStart,
|
|
2714
|
+
Math.min(height - 2, pieceMaxY - 5)
|
|
2715
|
+
);
|
|
2716
|
+
const columnGradients = new Float32Array(width);
|
|
2717
|
+
for (let x = 1; x < width - 1; x++) {
|
|
2718
|
+
let gradient = 0;
|
|
2719
|
+
for (let y = yStart; y <= yEnd; y++) {
|
|
2720
|
+
const left = (y * width + x - 1) * 4;
|
|
2721
|
+
const right = (y * width + x + 1) * 4;
|
|
2722
|
+
gradient += Math.abs(backgroundData[right] - backgroundData[left]) + Math.abs(backgroundData[right + 1] - backgroundData[left + 1]) + Math.abs(backgroundData[right + 2] - backgroundData[left + 2]);
|
|
2723
|
+
}
|
|
2724
|
+
columnGradients[x] = gradient;
|
|
2725
|
+
}
|
|
2726
|
+
let bestX = 0;
|
|
2727
|
+
let bestScore = 0;
|
|
2728
|
+
const minCandidateX = 30;
|
|
2729
|
+
const maxCandidateX = width - puzzleWidth - 20;
|
|
2730
|
+
for (let candidateX = minCandidateX; candidateX <= maxCandidateX; candidateX++) {
|
|
2731
|
+
let leftMax = 0;
|
|
2732
|
+
for (let dx = -2; dx <= 2; dx++) {
|
|
2733
|
+
const value = columnGradients[candidateX + pieceMinX + dx] || 0;
|
|
2734
|
+
if (value > leftMax) leftMax = value;
|
|
2735
|
+
}
|
|
2736
|
+
let rightMax = 0;
|
|
2737
|
+
for (let dx = -3; dx <= 1; dx++) {
|
|
2738
|
+
const value = columnGradients[candidateX + pieceMaxX + dx] || 0;
|
|
2739
|
+
if (value > rightMax) rightMax = value;
|
|
2740
|
+
}
|
|
2741
|
+
const score = Math.sqrt(leftMax * rightMax);
|
|
2742
|
+
if (score > bestScore) {
|
|
2743
|
+
bestScore = score;
|
|
2744
|
+
bestX = candidateX;
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
if (bestScore <= 0) {
|
|
2748
|
+
return { ok: false, reason: "no matching hole edge" };
|
|
2749
|
+
}
|
|
2750
|
+
return {
|
|
2751
|
+
ok: true,
|
|
2752
|
+
offsetX: bestX - pieceMinX,
|
|
2753
|
+
naturalWidth: width
|
|
2754
|
+
};
|
|
2755
|
+
} catch (error) {
|
|
2756
|
+
return {
|
|
2757
|
+
ok: false,
|
|
2758
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
2759
|
+
};
|
|
2760
|
+
}
|
|
2761
|
+
};
|
|
2762
|
+
return new Promise((resolve) => {
|
|
2763
|
+
if (background.complete && piece.complete) {
|
|
2764
|
+
resolve(compute());
|
|
2765
|
+
return;
|
|
2766
|
+
}
|
|
2767
|
+
let settled = false;
|
|
2768
|
+
const finish = () => {
|
|
2769
|
+
if (settled) return;
|
|
2770
|
+
settled = true;
|
|
2771
|
+
resolve(compute());
|
|
2772
|
+
};
|
|
2773
|
+
const fail = () => {
|
|
2774
|
+
if (settled) return;
|
|
2775
|
+
settled = true;
|
|
2776
|
+
resolve({ ok: false, reason: "puzzle image load error" });
|
|
2777
|
+
};
|
|
2778
|
+
background.addEventListener("load", finish, { once: true });
|
|
2779
|
+
piece.addEventListener("load", finish, { once: true });
|
|
2780
|
+
background.addEventListener("error", fail, { once: true });
|
|
2781
|
+
piece.addEventListener("error", fail, { once: true });
|
|
2782
|
+
setTimeout(() => {
|
|
2783
|
+
if (settled) return;
|
|
2784
|
+
settled = true;
|
|
2785
|
+
resolve({ ok: false, reason: "puzzle image load timeout" });
|
|
2786
|
+
}, 2e3);
|
|
2787
|
+
});
|
|
2788
|
+
});
|
|
2789
|
+
}
|
|
2790
|
+
async function solveAliyunWafCaptcha(page, options = {}) {
|
|
2791
|
+
const waitForMs = Math.max(0, options.waitForMs ?? 0);
|
|
2792
|
+
const maxAttempts = Math.max(
|
|
2793
|
+
1,
|
|
2794
|
+
Math.min(5, options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS)
|
|
2795
|
+
);
|
|
2796
|
+
const retryDelayMs = Math.max(
|
|
2797
|
+
0,
|
|
2798
|
+
options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS
|
|
2799
|
+
);
|
|
2800
|
+
const settleMs = Math.max(0, options.settleMs ?? DEFAULT_SETTLE_MS);
|
|
2801
|
+
const sliderTimeoutMs = Math.max(
|
|
2802
|
+
500,
|
|
2803
|
+
options.sliderTimeoutMs ?? DEFAULT_SLIDER_TIMEOUT_MS
|
|
2804
|
+
);
|
|
2805
|
+
const detected = await findVisibleLocatorWithin(
|
|
2806
|
+
page,
|
|
2807
|
+
ALIYUN_WAF_BLOCK_SELECTORS,
|
|
2808
|
+
waitForMs
|
|
2809
|
+
);
|
|
2810
|
+
if (!detected) return false;
|
|
2811
|
+
return withCaptchaMouseLock(async () => {
|
|
2812
|
+
const block = detected.locator;
|
|
2813
|
+
if (!await isVisible(block)) return false;
|
|
2814
|
+
logBaxiaCaptcha("aliyun_detected", { selector: detected.selector });
|
|
2815
|
+
let lastReason = "unknown";
|
|
2816
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
2817
|
+
try {
|
|
2818
|
+
const offset = await computeAliyunPuzzleOffset(page);
|
|
2819
|
+
if (!offset.ok || typeof offset.offsetX !== "number" || typeof offset.naturalWidth !== "number" || offset.naturalWidth <= 0) {
|
|
2820
|
+
lastReason = offset.reason || "offset_unavailable";
|
|
2821
|
+
logBaxiaCaptcha("aliyun_offset_failed", {
|
|
2822
|
+
attempt,
|
|
2823
|
+
reason: lastReason
|
|
2824
|
+
});
|
|
2825
|
+
} else {
|
|
2826
|
+
const slider = page.locator(ALIYUN_PUZZLE_SLIDER_SELECTOR).first();
|
|
2827
|
+
const track = page.locator(ALIYUN_PUZZLE_TRACK_SELECTOR).first();
|
|
2828
|
+
await slider.waitFor({ state: "visible", timeout: sliderTimeoutMs });
|
|
2829
|
+
const [sliderBox, trackBox] = await Promise.all([
|
|
2830
|
+
slider.boundingBox(),
|
|
2831
|
+
track.boundingBox()
|
|
2832
|
+
]);
|
|
2833
|
+
if (!sliderBox || !trackBox || trackBox.width <= 0) {
|
|
2834
|
+
lastReason = "bounds_unavailable";
|
|
2835
|
+
logBaxiaCaptcha("aliyun_offset_failed", {
|
|
2836
|
+
attempt,
|
|
2837
|
+
reason: lastReason
|
|
2838
|
+
});
|
|
2839
|
+
} else {
|
|
2840
|
+
const scale = trackBox.width / offset.naturalWidth;
|
|
2841
|
+
const dragDistance = Math.round(offset.offsetX * scale);
|
|
2842
|
+
logBaxiaCaptcha("aliyun_geometry", {
|
|
2843
|
+
attempt,
|
|
2844
|
+
offset: offset.offsetX,
|
|
2845
|
+
scale: Number(scale.toFixed(2)),
|
|
2846
|
+
distance: dragDistance
|
|
2847
|
+
});
|
|
2848
|
+
if (dragDistance <= 0) {
|
|
2849
|
+
lastReason = "non_positive_distance";
|
|
2850
|
+
} else {
|
|
2851
|
+
const startX = sliderBox.x + sliderBox.width / 2;
|
|
2852
|
+
const startY = sliderBox.y + sliderBox.height / 2;
|
|
2853
|
+
await humanDrag(
|
|
2854
|
+
page,
|
|
2855
|
+
startX,
|
|
2856
|
+
startY,
|
|
2857
|
+
startX + dragDistance,
|
|
2858
|
+
startY
|
|
2859
|
+
);
|
|
2860
|
+
if (await waitForHidden(block, settleMs)) {
|
|
2861
|
+
logBaxiaCaptcha(
|
|
2862
|
+
"aliyun_solve_succeeded",
|
|
2863
|
+
{ attempt, distance: dragDistance },
|
|
2864
|
+
true
|
|
2865
|
+
);
|
|
2866
|
+
return true;
|
|
2867
|
+
}
|
|
2868
|
+
lastReason = "not_solved";
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
} catch (error) {
|
|
2873
|
+
lastReason = error instanceof Error ? error.name : "UnknownError";
|
|
2874
|
+
logBaxiaCaptcha("aliyun_offset_failed", {
|
|
2875
|
+
attempt,
|
|
2876
|
+
error: lastReason,
|
|
2877
|
+
detail: sanitizeCaptchaErrorDetail(error)
|
|
2878
|
+
});
|
|
2879
|
+
}
|
|
2880
|
+
if (attempt < maxAttempts && retryDelayMs > 0) {
|
|
2881
|
+
await sleep(retryDelayMs);
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
logBaxiaCaptcha(
|
|
2885
|
+
"aliyun_solve_failed",
|
|
2886
|
+
{ attempts: maxAttempts, reason: lastReason },
|
|
2887
|
+
true
|
|
2888
|
+
);
|
|
2889
|
+
return false;
|
|
2890
|
+
});
|
|
2891
|
+
}
|
|
2892
|
+
async function solveVisibleCaptcha(page, options = {}) {
|
|
2893
|
+
if (typeof page.isClosed === "function" && page.isClosed()) return false;
|
|
2894
|
+
const totalWaitMs = Math.max(0, options.waitForMs ?? 0);
|
|
2895
|
+
const aliyunWaitMs = Math.min(totalWaitMs, ALIYUN_PROBE_MAX_WAIT_MS);
|
|
2896
|
+
const startedAt = Date.now();
|
|
2897
|
+
if (await solveAliyunWafCaptcha(page, { ...options, waitForMs: aliyunWaitMs })) {
|
|
2898
|
+
return true;
|
|
2899
|
+
}
|
|
2900
|
+
const remainingWaitMs = Math.max(
|
|
2901
|
+
0,
|
|
2902
|
+
totalWaitMs - (Date.now() - startedAt)
|
|
2903
|
+
);
|
|
2904
|
+
return solveBaxiaCaptcha(page, { ...options, waitForMs: remainingWaitMs });
|
|
2905
|
+
}
|
|
2615
2906
|
async function isVisible(locator) {
|
|
2616
2907
|
return locator.isVisible().catch(() => false);
|
|
2617
2908
|
}
|
|
@@ -2854,7 +3145,7 @@ async function solveBaxiaCaptchaUnlocked(page, options = {}) {
|
|
|
2854
3145
|
);
|
|
2855
3146
|
return false;
|
|
2856
3147
|
}
|
|
2857
|
-
var BAXIA_DIALOG_SELECTOR, BAXIA_CONTENT_SELECTOR, CAPTCHA_EVENT_EMOJI, captchaDebugEnabled, BAXIA_IFRAME_SELECTORS, BAXIA_DOCUMENT_SELECTORS, BAXIA_IFRAME_SELECTOR, BAXIA_SLIDER_SELECTOR, BAXIA_TRACK_SELECTOR, BAXIA_SUCCESS_SELECTOR, BAXIA_RELOAD_SELECTOR, DEFAULT_MAX_ATTEMPTS, DEFAULT_RETRY_DELAY_MS, DEFAULT_SETTLE_MS, DEFAULT_SLIDER_TIMEOUT_MS, captchaMouseLock;
|
|
3148
|
+
var BAXIA_DIALOG_SELECTOR, BAXIA_CONTENT_SELECTOR, CAPTCHA_EVENT_EMOJI, captchaDebugEnabled, BAXIA_IFRAME_SELECTORS, BAXIA_DOCUMENT_SELECTORS, BAXIA_IFRAME_SELECTOR, BAXIA_SLIDER_SELECTOR, BAXIA_TRACK_SELECTOR, BAXIA_SUCCESS_SELECTOR, BAXIA_RELOAD_SELECTOR, DEFAULT_MAX_ATTEMPTS, DEFAULT_RETRY_DELAY_MS, DEFAULT_SETTLE_MS, DEFAULT_SLIDER_TIMEOUT_MS, ALIYUN_WAF_CAPTCHA_SELECTOR, ALIYUN_WAF_CAPTCHA_WIDGET, ALIYUN_WAF_BLOCK_SELECTORS, ALIYUN_PUZZLE_SLIDER_SELECTOR, ALIYUN_PUZZLE_TRACK_SELECTOR, ALIYUN_PROBE_MAX_WAIT_MS, captchaMouseLock;
|
|
2858
3149
|
var init_captcha_solver = __esm({
|
|
2859
3150
|
"src/services/captcha-solver.ts"() {
|
|
2860
3151
|
"use strict";
|
|
@@ -2880,14 +3171,20 @@ var init_captcha_solver = __esm({
|
|
|
2880
3171
|
solve_failed: "\u274C",
|
|
2881
3172
|
recovery_succeeded: "\u2705",
|
|
2882
3173
|
recovery_not_solved: "\u26A0\uFE0F",
|
|
2883
|
-
recovery_failed: "\u274C"
|
|
3174
|
+
recovery_failed: "\u274C",
|
|
3175
|
+
aliyun_detected: "\u{1F9E9}",
|
|
3176
|
+
aliyun_offset_failed: "\u{1F4D0}",
|
|
3177
|
+
aliyun_geometry: "\u{1F4D0}",
|
|
3178
|
+
aliyun_solve_succeeded: "\u2705",
|
|
3179
|
+
aliyun_solve_failed: "\u274C"
|
|
2884
3180
|
};
|
|
2885
3181
|
captchaDebugEnabled = process.env.CAPTCHA_DEBUG === "true";
|
|
2886
3182
|
BAXIA_IFRAME_SELECTORS = [
|
|
2887
3183
|
`${BAXIA_DIALOG_SELECTOR} ${BAXIA_CONTENT_SELECTOR} iframe`,
|
|
2888
3184
|
`${BAXIA_CONTENT_SELECTOR} iframe`,
|
|
2889
3185
|
"iframe#baxia-dialog-content",
|
|
2890
|
-
'iframe[src*="_____tmd_____/punish"]'
|
|
3186
|
+
'iframe[src*="_____tmd_____/punish"]',
|
|
3187
|
+
'iframe[src*="nocaptcha"]'
|
|
2891
3188
|
];
|
|
2892
3189
|
BAXIA_DOCUMENT_SELECTORS = [
|
|
2893
3190
|
"#nocaptcha",
|
|
@@ -2895,14 +3192,23 @@ var init_captcha_solver = __esm({
|
|
|
2895
3192
|
"#baxia-punish"
|
|
2896
3193
|
];
|
|
2897
3194
|
BAXIA_IFRAME_SELECTOR = BAXIA_IFRAME_SELECTORS.join(", ");
|
|
2898
|
-
BAXIA_SLIDER_SELECTOR =
|
|
2899
|
-
BAXIA_TRACK_SELECTOR =
|
|
3195
|
+
BAXIA_SLIDER_SELECTOR = '#nc_1_n1z, .nc_1_n1z, .btn_slide, .nc_iconfont.btn_slide, span[id*="_n1z"], .nc_wrapper .btn_slide, ._nc .btn_slide, .nc-container .btn_slide';
|
|
3196
|
+
BAXIA_TRACK_SELECTOR = '#nc_1_n1t, .nc_scale, span[id*="_n1t"], .nc_wrapper .nc_scale, ._nc .nc_scale, .nc-container .nc_scale';
|
|
2900
3197
|
BAXIA_SUCCESS_SELECTOR = '.btn_ok, .nc_ok, .nc_success, .nc_result, .nc_wrapper.nc-success, .nc_wrapper.success, [data-nc-lang="SUCCESS"], [data-nc-lang="success"], #nc-loading-circle';
|
|
2901
3198
|
BAXIA_RELOAD_SELECTOR = '#nc_1_refresh1, .errloading a, .nc-container .errloading a, .btn_refresh, .clickCaptcha_text .btn_refresh, [data-nc-lang="REFRESH"], a[id*="refresh"]';
|
|
2902
3199
|
DEFAULT_MAX_ATTEMPTS = 3;
|
|
2903
3200
|
DEFAULT_RETRY_DELAY_MS = 1e3;
|
|
2904
3201
|
DEFAULT_SETTLE_MS = 2e3;
|
|
2905
3202
|
DEFAULT_SLIDER_TIMEOUT_MS = 8e3;
|
|
3203
|
+
ALIYUN_WAF_CAPTCHA_SELECTOR = "#waf_nc_block";
|
|
3204
|
+
ALIYUN_WAF_CAPTCHA_WIDGET = "#aliyunCaptcha-window-embed";
|
|
3205
|
+
ALIYUN_WAF_BLOCK_SELECTORS = [
|
|
3206
|
+
ALIYUN_WAF_CAPTCHA_SELECTOR,
|
|
3207
|
+
ALIYUN_WAF_CAPTCHA_WIDGET
|
|
3208
|
+
];
|
|
3209
|
+
ALIYUN_PUZZLE_SLIDER_SELECTOR = "#aliyunCaptcha-sliding-slider";
|
|
3210
|
+
ALIYUN_PUZZLE_TRACK_SELECTOR = "#aliyunCaptcha-sliding-body";
|
|
3211
|
+
ALIYUN_PROBE_MAX_WAIT_MS = 2e3;
|
|
2906
3212
|
captchaMouseLock = Promise.resolve();
|
|
2907
3213
|
}
|
|
2908
3214
|
});
|
|
@@ -2993,7 +3299,15 @@ function updateQwenWebVersion(version) {
|
|
|
2993
3299
|
function getQwenWebVersion() {
|
|
2994
3300
|
return dynamicWebVersion || config.qwen.webVersion;
|
|
2995
3301
|
}
|
|
2996
|
-
|
|
3302
|
+
function updateQwenBxVersion(version) {
|
|
3303
|
+
if (version && typeof version === "string" && /^\d+\.\d+\.\d+/.test(version)) {
|
|
3304
|
+
dynamicBxVersion = version.trim();
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
function getQwenBxVersion() {
|
|
3308
|
+
return dynamicBxVersion || config.auth.bxV;
|
|
3309
|
+
}
|
|
3310
|
+
var dynamicWebVersion, dynamicBxVersion, QWEN_WEB_VERSION, DEFAULT_QWEN_USER_AGENT, QWEN_TIMEZONE_HEADER;
|
|
2997
3311
|
var init_qwen_headers = __esm({
|
|
2998
3312
|
"src/services/qwen-headers.ts"() {
|
|
2999
3313
|
"use strict";
|
|
@@ -3002,6 +3316,7 @@ var init_qwen_headers = __esm({
|
|
|
3002
3316
|
init_fingerprint();
|
|
3003
3317
|
init_timezone();
|
|
3004
3318
|
dynamicWebVersion = null;
|
|
3319
|
+
dynamicBxVersion = null;
|
|
3005
3320
|
QWEN_WEB_VERSION = config.qwen.webVersion;
|
|
3006
3321
|
DEFAULT_QWEN_USER_AGENT = getDefaultQwenUserAgent(151);
|
|
3007
3322
|
QWEN_TIMEZONE_HEADER = (/* @__PURE__ */ new Date()).toString().split(" (")[0];
|
|
@@ -3615,11 +3930,12 @@ async function getOrLaunchSharedBrowser(browserType = "chromium", headless = con
|
|
|
3615
3930
|
async function clearVisibleChallenge(page) {
|
|
3616
3931
|
if (page.isClosed()) return;
|
|
3617
3932
|
if (config.captcha.enabled) {
|
|
3618
|
-
await
|
|
3933
|
+
await solveVisibleCaptcha(page, {
|
|
3619
3934
|
waitForMs: 0,
|
|
3620
3935
|
maxAttempts: config.captcha.maxAttempts,
|
|
3621
3936
|
retryDelayMs: config.captcha.retryDelayMs,
|
|
3622
|
-
settleMs: config.captcha.settleMs
|
|
3937
|
+
settleMs: config.captcha.settleMs,
|
|
3938
|
+
sliderTimeoutMs: config.captcha.sliderTimeoutMs
|
|
3623
3939
|
}).catch(() => false);
|
|
3624
3940
|
}
|
|
3625
3941
|
try {
|
|
@@ -4232,6 +4548,7 @@ async function getBasicHeaders(accountId) {
|
|
|
4232
4548
|
mobile = data.mobile ? "?1" : "?0";
|
|
4233
4549
|
}
|
|
4234
4550
|
let bundleVersion = null;
|
|
4551
|
+
let baxiaVersion = null;
|
|
4235
4552
|
try {
|
|
4236
4553
|
const el = document.querySelector('link[href*="qwen-chat-fe"], script[src*="qwen-chat-fe"], img[src*="qwen-chat-fe"]');
|
|
4237
4554
|
const src = el ? el.getAttribute("href") || el.getAttribute("src") || "" : "";
|
|
@@ -4239,7 +4556,14 @@ async function getBasicHeaders(accountId) {
|
|
|
4239
4556
|
if (match) bundleVersion = match[1];
|
|
4240
4557
|
} catch {
|
|
4241
4558
|
}
|
|
4242
|
-
|
|
4559
|
+
try {
|
|
4560
|
+
const baxia = window.baxiaCommon;
|
|
4561
|
+
if (typeof baxia?.version === "string") {
|
|
4562
|
+
baxiaVersion = baxia.version;
|
|
4563
|
+
}
|
|
4564
|
+
} catch {
|
|
4565
|
+
}
|
|
4566
|
+
return { ua, secChUa, platform, mobile, bundleVersion, baxiaVersion };
|
|
4243
4567
|
}),
|
|
4244
4568
|
config.timeouts.page,
|
|
4245
4569
|
`User-agent lookup timed out for ${accountId}`
|
|
@@ -4248,6 +4572,9 @@ async function getBasicHeaders(accountId) {
|
|
|
4248
4572
|
if (nav.bundleVersion) {
|
|
4249
4573
|
updateQwenWebVersion(nav.bundleVersion);
|
|
4250
4574
|
}
|
|
4575
|
+
if (nav.baxiaVersion) {
|
|
4576
|
+
updateQwenBxVersion(nav.baxiaVersion);
|
|
4577
|
+
}
|
|
4251
4578
|
cachedUserAgents.set(accountId, userAgent);
|
|
4252
4579
|
const hints = getHeaderCache(accountId).headers;
|
|
4253
4580
|
clientHints = {
|
|
@@ -4279,7 +4606,7 @@ async function getBasicHeaders(accountId) {
|
|
|
4279
4606
|
markAccountHeadersReady(accountId);
|
|
4280
4607
|
const bxUa2 = cache.headers["bx-ua"];
|
|
4281
4608
|
const bxUmidtoken2 = cache.headers["bx-umidtoken"];
|
|
4282
|
-
const bxV2 = cache.headers["bx-v"] ||
|
|
4609
|
+
const bxV2 = cache.headers["bx-v"] || getQwenBxVersion();
|
|
4283
4610
|
const cookie2 = await getCookies(accountId);
|
|
4284
4611
|
return { cookie: cookie2, userAgent, bxV: bxV2, bxUa: bxUa2, bxUmidtoken: bxUmidtoken2, ...clientHints };
|
|
4285
4612
|
}
|
|
@@ -4290,7 +4617,7 @@ async function getBasicHeaders(accountId) {
|
|
|
4290
4617
|
cookieCaches.set(accountId, { cookie: cookie2, timestamp: Date.now() });
|
|
4291
4618
|
const bxUa2 = cache.headers["bx-ua"];
|
|
4292
4619
|
const bxUmidtoken2 = cache.headers["bx-umidtoken"];
|
|
4293
|
-
const bxV2 = cache.headers["bx-v"] ||
|
|
4620
|
+
const bxV2 = cache.headers["bx-v"] || getQwenBxVersion();
|
|
4294
4621
|
cache.lastRefresh = Date.now();
|
|
4295
4622
|
markAccountHeadersReady(accountId);
|
|
4296
4623
|
console.log(
|
|
@@ -4310,14 +4637,15 @@ async function getBasicHeaders(accountId) {
|
|
|
4310
4637
|
`\u26A0\uFE0F [Playwright] Header refresh failed for ${accountId}; retaining the previous valid cache: ${getErrorMessage(error)}`
|
|
4311
4638
|
);
|
|
4312
4639
|
}
|
|
4313
|
-
} else if (hadUsableHeaders && headersAge > HEADER_CACHE_TTL * HEADER_REFRESH_THRESHOLD && !cache.refreshInProgress
|
|
4314
|
-
|
|
4640
|
+
} else if (hadUsableHeaders && headersAge > HEADER_CACHE_TTL * HEADER_REFRESH_THRESHOLD && !cache.refreshInProgress && // Header capture types into the chat input and sends a probe message on
|
|
4641
|
+
// the account's page. Doing that while the account is serving a stream
|
|
4642
|
+
// would mutate the live conversation (and can navigate the SPA), so the
|
|
4643
|
+
// proactive refresh waits until the account has no active lease.
|
|
4644
|
+
!hasActiveAccountLease(accountId)) {
|
|
4315
4645
|
refreshHeadersInternal(accountId).catch((error) => {
|
|
4316
4646
|
console.warn(
|
|
4317
4647
|
`\u26A0\uFE0F [Playwright] Background header refresh failed for ${accountId}: ${getErrorMessage(error)}`
|
|
4318
4648
|
);
|
|
4319
|
-
}).finally(() => {
|
|
4320
|
-
cache.refreshInProgress = false;
|
|
4321
4649
|
});
|
|
4322
4650
|
}
|
|
4323
4651
|
if (!hasRequiredQwenHeaders(cache.headers)) {
|
|
@@ -4364,6 +4692,9 @@ async function getBasicHeaders(accountId) {
|
|
|
4364
4692
|
if (persisted.version) {
|
|
4365
4693
|
updateQwenWebVersion(persisted.version);
|
|
4366
4694
|
}
|
|
4695
|
+
if (persisted.bxV) {
|
|
4696
|
+
updateQwenBxVersion(persisted.bxV);
|
|
4697
|
+
}
|
|
4367
4698
|
cache.lastRefresh = persisted.capturedAt;
|
|
4368
4699
|
markAccountHeadersReady(accountId);
|
|
4369
4700
|
}
|
|
@@ -4391,7 +4722,7 @@ async function getBasicHeaders(accountId) {
|
|
|
4391
4722
|
markAccountHeadersReady(accountId);
|
|
4392
4723
|
const bxUa = cache.headers["bx-ua"];
|
|
4393
4724
|
const bxUmidtoken = cache.headers["bx-umidtoken"];
|
|
4394
|
-
const bxV = cache.headers["bx-v"] ||
|
|
4725
|
+
const bxV = cache.headers["bx-v"] || getQwenBxVersion();
|
|
4395
4726
|
cookieCaches.delete(accountId);
|
|
4396
4727
|
const cookie = await getCookies(accountId, true);
|
|
4397
4728
|
if (cache.headers) {
|
|
@@ -4455,8 +4786,12 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
|
|
|
4455
4786
|
if (accountPages.has(account.id)) {
|
|
4456
4787
|
return;
|
|
4457
4788
|
}
|
|
4458
|
-
|
|
4459
|
-
|
|
4789
|
+
if (config.playwright.maxActiveContexts > 0) {
|
|
4790
|
+
await evictIdlePlaywrightContextsToLimit(
|
|
4791
|
+
Math.max(1, config.playwright.maxActiveContexts - 1)
|
|
4792
|
+
).catch(() => {
|
|
4793
|
+
});
|
|
4794
|
+
}
|
|
4460
4795
|
const profilePath = getAccountProfilePath(account.id);
|
|
4461
4796
|
const fingerprint = getFingerprintProfile(account.id);
|
|
4462
4797
|
const { engine, channel } = resolveBrowserEngine(browserType);
|
|
@@ -4632,6 +4967,9 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
|
|
|
4632
4967
|
if (persisted.version) {
|
|
4633
4968
|
updateQwenWebVersion(persisted.version);
|
|
4634
4969
|
}
|
|
4970
|
+
if (persisted.bxV) {
|
|
4971
|
+
updateQwenBxVersion(persisted.bxV);
|
|
4972
|
+
}
|
|
4635
4973
|
cache.lastRefresh = persisted.capturedAt;
|
|
4636
4974
|
markAccountHeadersReady(account.id);
|
|
4637
4975
|
restoredFromDb = true;
|
|
@@ -4725,7 +5063,7 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
|
|
|
4725
5063
|
if (!acctPage.isClosed()) {
|
|
4726
5064
|
try {
|
|
4727
5065
|
const currentUrl = new URL(acctPage.url());
|
|
4728
|
-
if (currentUrl.origin !== qwenOrigin() || currentUrl.pathname
|
|
5066
|
+
if (currentUrl.origin !== qwenOrigin() || currentUrl.pathname.includes("/auth") || currentUrl.pathname.includes("/login") || currentUrl.pathname.includes("_____tmd_____")) {
|
|
4729
5067
|
await acctPage.goto(qwenUrl("/"), {
|
|
4730
5068
|
waitUntil: "domcontentloaded",
|
|
4731
5069
|
timeout: config.timeouts.navigation
|
|
@@ -4743,6 +5081,8 @@ async function initPlaywrightForAccount(rawAccount, headless = config.playwright
|
|
|
4743
5081
|
} finally {
|
|
4744
5082
|
release();
|
|
4745
5083
|
}
|
|
5084
|
+
await evictIdlePlaywrightContextsToLimit().catch(() => {
|
|
5085
|
+
});
|
|
4746
5086
|
})();
|
|
4747
5087
|
try {
|
|
4748
5088
|
await initPromise;
|
|
@@ -4979,7 +5319,7 @@ async function startEmailOtpLogin(email, options = {}) {
|
|
|
4979
5319
|
{
|
|
4980
5320
|
email: normalizedEmail,
|
|
4981
5321
|
requestId,
|
|
4982
|
-
version: getQwenWebVersion()
|
|
5322
|
+
version: getQwenWebVersion(),
|
|
4983
5323
|
timezone: formatAsciiTimezone()
|
|
4984
5324
|
}
|
|
4985
5325
|
).catch((err) => ({ ok: false, error: err?.message || String(err) }));
|
|
@@ -5074,7 +5414,7 @@ async function verifyEmailOtpLogin(sessionId, code) {
|
|
|
5074
5414
|
email: session.email,
|
|
5075
5415
|
code: cleanCode,
|
|
5076
5416
|
requestId,
|
|
5077
|
-
version: getQwenWebVersion()
|
|
5417
|
+
version: getQwenWebVersion(),
|
|
5078
5418
|
timezone: formatAsciiTimezone()
|
|
5079
5419
|
}
|
|
5080
5420
|
).catch((err) => ({ ok: false, error: err?.message || String(err) }));
|
|
@@ -5121,8 +5461,8 @@ async function verifyEmailOtpLogin(sessionId, code) {
|
|
|
5121
5461
|
saveAuthSession2(session.accountId, {
|
|
5122
5462
|
cookie: `token=${accessToken}`,
|
|
5123
5463
|
userAgent: session.fingerprint.userAgent,
|
|
5124
|
-
bxV:
|
|
5125
|
-
version: getQwenWebVersion()
|
|
5464
|
+
bxV: getQwenBxVersion(),
|
|
5465
|
+
version: getQwenWebVersion(),
|
|
5126
5466
|
userId: userId || void 0,
|
|
5127
5467
|
tokenExpiresAt: exp || void 0,
|
|
5128
5468
|
refreshToken: refreshToken || void 0,
|
|
@@ -5232,7 +5572,7 @@ async function loginToQwen(accountId, email, password) {
|
|
|
5232
5572
|
saveAuthSession2(accountId, {
|
|
5233
5573
|
cookie: cookieStr,
|
|
5234
5574
|
userAgent: cache.headers["user-agent"] || "",
|
|
5235
|
-
bxV: cache.headers["bx-v"] ||
|
|
5575
|
+
bxV: cache.headers["bx-v"] || getQwenBxVersion(),
|
|
5236
5576
|
bxUa: cache.headers["bx-ua"] || "",
|
|
5237
5577
|
bxUmidtoken: cache.headers["bx-umidtoken"] || "",
|
|
5238
5578
|
secChUa: cache.headers["sec-ch-ua"] || void 0,
|
|
@@ -5304,7 +5644,7 @@ async function loginToQwen(accountId, email, password) {
|
|
|
5304
5644
|
saveAuthSession2(accountId, {
|
|
5305
5645
|
cookie: cookieStr,
|
|
5306
5646
|
userAgent: cache.headers["user-agent"] || "",
|
|
5307
|
-
bxV: cache.headers["bx-v"] ||
|
|
5647
|
+
bxV: cache.headers["bx-v"] || getQwenBxVersion(),
|
|
5308
5648
|
bxUa: cache.headers["bx-ua"] || "",
|
|
5309
5649
|
bxUmidtoken: cache.headers["bx-umidtoken"] || "",
|
|
5310
5650
|
secChUa: cache.headers["sec-ch-ua"] || void 0,
|
|
@@ -5375,7 +5715,7 @@ async function loginViaApi(page, email, password) {
|
|
|
5375
5715
|
}
|
|
5376
5716
|
const signinUrl = "https://auth.qwen.ai/api/v2/auths/signin";
|
|
5377
5717
|
const requestId = crypto3.randomUUID();
|
|
5378
|
-
const webVersion = getQwenWebVersion()
|
|
5718
|
+
const webVersion = getQwenWebVersion();
|
|
5379
5719
|
const evalRes = await page.evaluate(
|
|
5380
5720
|
async ({ email: email2, password: password2, signinUrl: signinUrl2, requestId: requestId2, tz, version }) => {
|
|
5381
5721
|
try {
|
|
@@ -5547,6 +5887,15 @@ async function loginViaUi(page, email, password) {
|
|
|
5547
5887
|
if (!page.url().includes("/auth") && await isPageLoggedIn(page, 3e3).catch(() => false)) {
|
|
5548
5888
|
return { success: true };
|
|
5549
5889
|
}
|
|
5890
|
+
if (config.captcha.enabled) {
|
|
5891
|
+
await solveVisibleCaptcha(page, {
|
|
5892
|
+
waitForMs: 1500,
|
|
5893
|
+
maxAttempts: config.captcha.maxAttempts,
|
|
5894
|
+
retryDelayMs: config.captcha.retryDelayMs,
|
|
5895
|
+
settleMs: config.captcha.settleMs,
|
|
5896
|
+
sliderTimeoutMs: config.captcha.sliderTimeoutMs
|
|
5897
|
+
}).catch(() => false);
|
|
5898
|
+
}
|
|
5550
5899
|
const emailSelector = [
|
|
5551
5900
|
'input[type="email"]',
|
|
5552
5901
|
'input[name="email"]',
|
|
@@ -5702,10 +6051,11 @@ async function loginViaUi(page, email, password) {
|
|
|
5702
6051
|
while (Date.now() < postSubmitDeadline) {
|
|
5703
6052
|
if (page.isClosed()) break;
|
|
5704
6053
|
if (config.captcha.enabled) {
|
|
5705
|
-
await
|
|
6054
|
+
await solveVisibleCaptcha(page, {
|
|
5706
6055
|
waitForMs: 1500,
|
|
5707
6056
|
maxAttempts: config.captcha.maxAttempts,
|
|
5708
|
-
retryDelayMs: config.captcha.retryDelayMs
|
|
6057
|
+
retryDelayMs: config.captcha.retryDelayMs,
|
|
6058
|
+
sliderTimeoutMs: config.captcha.sliderTimeoutMs
|
|
5709
6059
|
}).catch(() => {
|
|
5710
6060
|
});
|
|
5711
6061
|
}
|
|
@@ -5828,7 +6178,7 @@ async function refreshAccountToken(accountId) {
|
|
|
5828
6178
|
}
|
|
5829
6179
|
if (refreshToken) {
|
|
5830
6180
|
try {
|
|
5831
|
-
const webVersion = getQwenWebVersion()
|
|
6181
|
+
const webVersion = getQwenWebVersion();
|
|
5832
6182
|
const refreshResult = await page.evaluate(
|
|
5833
6183
|
async ({ rTok, tz, version }) => {
|
|
5834
6184
|
try {
|
|
@@ -5893,7 +6243,7 @@ async function refreshAccountToken(accountId) {
|
|
|
5893
6243
|
saveAuthSession2(accountId, {
|
|
5894
6244
|
cookie: cookieStr,
|
|
5895
6245
|
userAgent: cache.headers["user-agent"] || session?.userAgent || "",
|
|
5896
|
-
bxV: cache.headers["bx-v"] || session?.bxV ||
|
|
6246
|
+
bxV: cache.headers["bx-v"] || session?.bxV || getQwenBxVersion(),
|
|
5897
6247
|
bxUa: cache.headers["bx-ua"] || session?.bxUa || "",
|
|
5898
6248
|
bxUmidtoken: cache.headers["bx-umidtoken"] || session?.bxUmidtoken || "",
|
|
5899
6249
|
secChUa: cache.headers["sec-ch-ua"] || session?.secChUa,
|
|
@@ -5928,7 +6278,7 @@ async function refreshAccountToken(accountId) {
|
|
|
5928
6278
|
saveAuthSession2(accountId, {
|
|
5929
6279
|
cookie: cookieStr,
|
|
5930
6280
|
userAgent: cache.headers["user-agent"] || session?.userAgent || "",
|
|
5931
|
-
bxV: cache.headers["bx-v"] || session?.bxV ||
|
|
6281
|
+
bxV: cache.headers["bx-v"] || session?.bxV || getQwenBxVersion(),
|
|
5932
6282
|
bxUa: cache.headers["bx-ua"] || session?.bxUa || "",
|
|
5933
6283
|
bxUmidtoken: cache.headers["bx-umidtoken"] || session?.bxUmidtoken || "",
|
|
5934
6284
|
secChUa: cache.headers["sec-ch-ua"] || session?.secChUa,
|
|
@@ -6076,7 +6426,7 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
|
|
|
6076
6426
|
cookie: reqHeaders["cookie"] || "",
|
|
6077
6427
|
"bx-ua": reqHeaders["bx-ua"] || "",
|
|
6078
6428
|
"bx-umidtoken": reqHeaders["bx-umidtoken"] || "",
|
|
6079
|
-
"bx-v": reqHeaders["bx-v"] ||
|
|
6429
|
+
"bx-v": reqHeaders["bx-v"] || getQwenBxVersion(),
|
|
6080
6430
|
"user-agent": reqHeaders["user-agent"] || "",
|
|
6081
6431
|
"x-request-id": reqHeaders["x-request-id"] || "",
|
|
6082
6432
|
"version": reqHeaders["version"] || "",
|
|
@@ -6108,6 +6458,9 @@ async function captureQwenHeaders(accountId, pageOverride, timeoutMs = config.ti
|
|
|
6108
6458
|
if (capturedHeaders["version"]) {
|
|
6109
6459
|
updateQwenWebVersion(capturedHeaders["version"]);
|
|
6110
6460
|
}
|
|
6461
|
+
if (capturedHeaders["bx-v"]) {
|
|
6462
|
+
updateQwenBxVersion(capturedHeaders["bx-v"]);
|
|
6463
|
+
}
|
|
6111
6464
|
markAccountHeadersReady(accountId);
|
|
6112
6465
|
cache.lastRefresh = Date.now();
|
|
6113
6466
|
cookieCaches.delete(accountId);
|
|
@@ -6511,19 +6864,26 @@ async function refreshHeadersInternal(accountId, timeoutMs = config.timeouts.hea
|
|
|
6511
6864
|
await executeReauth();
|
|
6512
6865
|
} else {
|
|
6513
6866
|
try {
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6867
|
+
const currentUrl = typeof page.url === "function" ? page.url() : "";
|
|
6868
|
+
const needsNavigation = !currentUrl.startsWith(qwenOrigin()) || currentUrl.includes("/auth") || currentUrl.includes("/login") || currentUrl.includes("_____tmd_____");
|
|
6869
|
+
if (needsNavigation) {
|
|
6870
|
+
await page.goto(qwenUrl("/"), {
|
|
6871
|
+
waitUntil: "domcontentloaded",
|
|
6872
|
+
timeout: Math.min(
|
|
6873
|
+
config.timeouts.navigation,
|
|
6874
|
+
boundedTimeoutMs,
|
|
6875
|
+
SESSION_PROBE_NAVIGATION_TIMEOUT_MS
|
|
6876
|
+
)
|
|
6877
|
+
});
|
|
6878
|
+
await sleep2(2e3);
|
|
6879
|
+
}
|
|
6880
|
+
const url = typeof page.url === "function" ? page.url() : "";
|
|
6524
6881
|
const isAuthUrl = url.includes("auth") || url.includes("login");
|
|
6525
6882
|
if (isAuthUrl) {
|
|
6526
|
-
await
|
|
6883
|
+
const refreshed = await refreshAccountToken(accountId);
|
|
6884
|
+
if (!refreshed.success) {
|
|
6885
|
+
await executeReauth();
|
|
6886
|
+
}
|
|
6527
6887
|
}
|
|
6528
6888
|
} catch (navErr) {
|
|
6529
6889
|
console.warn(
|
|
@@ -6558,7 +6918,7 @@ async function refreshHeadersInternal(accountId, timeoutMs = config.timeouts.hea
|
|
|
6558
6918
|
saveAuthSession2(accountId, {
|
|
6559
6919
|
cookie: cookieStr,
|
|
6560
6920
|
userAgent: cache.headers["user-agent"] || "",
|
|
6561
|
-
bxV: cache.headers["bx-v"] ||
|
|
6921
|
+
bxV: cache.headers["bx-v"] || getQwenBxVersion(),
|
|
6562
6922
|
bxUa: cache.headers["bx-ua"] || "",
|
|
6563
6923
|
bxUmidtoken: cache.headers["bx-umidtoken"] || "",
|
|
6564
6924
|
secChUa: cache.headers["sec-ch-ua"] || void 0,
|
|
@@ -6580,7 +6940,7 @@ async function refreshHeadersInternal(accountId, timeoutMs = config.timeouts.hea
|
|
|
6580
6940
|
if (capturedPage && !capturedPage.isClosed()) {
|
|
6581
6941
|
try {
|
|
6582
6942
|
const currentUrl = new URL(capturedPage.url());
|
|
6583
|
-
if (currentUrl.origin !== qwenOrigin() || currentUrl.pathname
|
|
6943
|
+
if (currentUrl.origin !== qwenOrigin() || currentUrl.pathname.includes("/auth") || currentUrl.pathname.includes("/login") || currentUrl.pathname.includes("_____tmd_____")) {
|
|
6584
6944
|
await capturedPage.goto(qwenUrl("/"), {
|
|
6585
6945
|
waitUntil: "domcontentloaded",
|
|
6586
6946
|
timeout: Math.min(config.timeouts.navigation, boundedTimeoutMs)
|
|
@@ -6896,7 +7256,11 @@ function priorityOrderForEviction(accountIds) {
|
|
|
6896
7256
|
const ranked = getAccountsByPriority(accountIds.map((id) => ({ id })));
|
|
6897
7257
|
const rank = /* @__PURE__ */ new Map();
|
|
6898
7258
|
for (const [index, account] of ranked.entries()) {
|
|
6899
|
-
|
|
7259
|
+
if (getAccountCooldownInfo(account.id)) {
|
|
7260
|
+
rank.set(account.id, Number.MAX_SAFE_INTEGER);
|
|
7261
|
+
} else {
|
|
7262
|
+
rank.set(account.id, index);
|
|
7263
|
+
}
|
|
6900
7264
|
}
|
|
6901
7265
|
return orderContextsForEviction(
|
|
6902
7266
|
accountIds,
|
|
@@ -6933,14 +7297,15 @@ async function closeIdlePlaywrightAccounts(idleMs) {
|
|
|
6933
7297
|
}
|
|
6934
7298
|
return closed;
|
|
6935
7299
|
}
|
|
6936
|
-
async function evictIdlePlaywrightContextsToLimit() {
|
|
6937
|
-
const
|
|
6938
|
-
if (
|
|
7300
|
+
async function evictIdlePlaywrightContextsToLimit(targetLimit) {
|
|
7301
|
+
const configuredMax = config.playwright.maxActiveContexts;
|
|
7302
|
+
if (configuredMax <= 0) return 0;
|
|
7303
|
+
const max = targetLimit !== void 0 ? Math.max(0, targetLimit) : configuredMax;
|
|
6939
7304
|
if (accountPages.size <= max) return 0;
|
|
6940
7305
|
const candidates = priorityOrderForEviction(
|
|
6941
7306
|
Array.from(accountPages.keys()).filter((accountId) => {
|
|
6942
7307
|
if (isAccountServingStream(accountId)) return false;
|
|
6943
|
-
if (
|
|
7308
|
+
if (hasActiveAccountLease(accountId)) return false;
|
|
6944
7309
|
const mutex = accountMutexes.get(accountId);
|
|
6945
7310
|
return mutex?.isIdle();
|
|
6946
7311
|
})
|
|
@@ -6953,6 +7318,7 @@ async function evictIdlePlaywrightContextsToLimit() {
|
|
|
6953
7318
|
for (const candidate of candidates) {
|
|
6954
7319
|
if (accountPages.size <= max) break;
|
|
6955
7320
|
if (isAccountServingStream(candidate.accountId)) continue;
|
|
7321
|
+
if (hasActiveAccountLease(candidate.accountId)) continue;
|
|
6956
7322
|
const mutex = accountMutexes.get(candidate.accountId);
|
|
6957
7323
|
if (!mutex?.isIdle()) continue;
|
|
6958
7324
|
await closePlaywrightForAccount(candidate.accountId).catch((error) => {
|