@sovovs/bycli 2.1.26 → 2.1.28
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
AuthRequiredError, CommandExecutionError, EmptyResultError,
|
|
2
|
+
AuthRequiredError, CliError, CommandExecutionError, EmptyResultError, RateLimitedError,
|
|
3
3
|
} from '@sovovs/bycli/errors';
|
|
4
4
|
import { buildSecretSet, redactText } from './redact.js';
|
|
5
5
|
|
|
@@ -16,12 +16,17 @@ function safePhase(error, secrets) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export function isEligibleArticleFallbackError(error) {
|
|
19
|
-
return error instanceof CommandExecutionError
|
|
19
|
+
return error instanceof CommandExecutionError
|
|
20
|
+
|| error instanceof EmptyResultError
|
|
21
|
+
|| (error instanceof CliError && error.code === 'RATE_LIMITED');
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export function withMissingFallbackName(operation, error) {
|
|
23
25
|
const hint = `${error.hint ? `${error.hint} ` : ''}Sogou fallback requires the exact official-account name in --name.`;
|
|
24
26
|
if (error instanceof EmptyResultError) return new EmptyResultError(operation, hint);
|
|
27
|
+
if (error instanceof CliError && error.code === 'RATE_LIMITED') {
|
|
28
|
+
return new RateLimitedError(error.message, hint);
|
|
29
|
+
}
|
|
25
30
|
return new CommandExecutionError(error.message, hint);
|
|
26
31
|
}
|
|
27
32
|
|
|
@@ -31,11 +36,17 @@ export function combineArticleFallbackErrors({
|
|
|
31
36
|
fallbackError,
|
|
32
37
|
credentials,
|
|
33
38
|
}) {
|
|
34
|
-
if (fallbackError instanceof AuthRequiredError) return fallbackError;
|
|
35
39
|
const secrets = buildSecretSet(credentials);
|
|
36
40
|
const primary = safePhase(primaryError, secrets);
|
|
37
41
|
const fallback = safePhase(fallbackError, secrets);
|
|
38
42
|
const hint = `Primary (${primary.code}): ${primary.summary}; fallback (${fallback.code}): ${fallback.summary}`;
|
|
43
|
+
if (primaryError instanceof CliError && primaryError.code === 'RATE_LIMITED') {
|
|
44
|
+
return new RateLimitedError(
|
|
45
|
+
'Weixin article index was rate limited and Sogou fallback failed',
|
|
46
|
+
hint,
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
if (fallbackError instanceof AuthRequiredError) return fallbackError;
|
|
39
50
|
if (primaryError instanceof EmptyResultError && fallbackError instanceof EmptyResultError) {
|
|
40
51
|
return new EmptyResultError(operation, hint);
|
|
41
52
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthRequiredError, CommandExecutionError } from '@sovovs/bycli/errors';
|
|
1
|
+
import { AuthRequiredError, CommandExecutionError, RateLimitedError } from '@sovovs/bycli/errors';
|
|
2
2
|
import { buildSecretSet, redactText } from './redact.js';
|
|
3
3
|
|
|
4
4
|
const DOMAIN = 'mp.weixin.qq.com';
|
|
@@ -34,8 +34,8 @@ export function mapArticleIndexPayload(payload) {
|
|
|
34
34
|
throw new AuthRequiredError(DOMAIN, 'WeChat article-index credentials have expired');
|
|
35
35
|
}
|
|
36
36
|
if (ret === 200013 && normalizedMessage === 'freq control') {
|
|
37
|
-
throw
|
|
38
|
-
'was rate limited (ret=200013)',
|
|
37
|
+
throw new RateLimitedError(
|
|
38
|
+
'WeChat appmsgpublish was rate limited (ret=200013)',
|
|
39
39
|
'Wait before retrying the WeChat article-index request; repeated retries may extend frequency control.',
|
|
40
40
|
);
|
|
41
41
|
}
|
|
@@ -122,6 +122,10 @@ function transportError(error, credentials) {
|
|
|
122
122
|
const redactedHint = hint ? redactText(hint, secrets) : undefined;
|
|
123
123
|
if (error instanceof AuthRequiredError && error.domain === DOMAIN
|
|
124
124
|
&& redactedMessage === message && redactedHint === hint) return error;
|
|
125
|
+
if (error instanceof RateLimitedError) {
|
|
126
|
+
if (redactedMessage === message && redactedHint === hint) return error;
|
|
127
|
+
return new RateLimitedError(redactedMessage, redactedHint);
|
|
128
|
+
}
|
|
125
129
|
if (isWechatVerificationResponse(redactedMessage, redactedHint)) {
|
|
126
130
|
return new AuthRequiredError(
|
|
127
131
|
DOMAIN,
|
|
@@ -102,21 +102,52 @@ async function fillField(page, selector, value) {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
async function fillContent(page, text) {
|
|
105
|
-
|
|
105
|
+
var result = await page.evaluate(`(() => {
|
|
106
|
+
var normalize = value => String(value ?? '').replace(/\\r\\n?/g, '\\n').trim();
|
|
107
|
+
var expected = normalize(${JSON.stringify(text)});
|
|
108
|
+
var instances = window.UE && window.UE.instants ? Object.values(window.UE.instants) : [];
|
|
109
|
+
var ueditor = instances.find(instance => instance
|
|
110
|
+
&& typeof instance.setContent === 'function'
|
|
111
|
+
&& typeof instance.getContentTxt === 'function');
|
|
112
|
+
if (ueditor && typeof ueditor.setContent === 'function' && typeof ueditor.getContentTxt === 'function') {
|
|
113
|
+
ueditor.setContent(${JSON.stringify(text)});
|
|
114
|
+
var ueditorActual = normalize(ueditor.getContentTxt());
|
|
115
|
+
if (ueditorActual === expected) {
|
|
116
|
+
return { ok: true, value: ueditorActual };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
106
119
|
var editors = document.querySelectorAll('div[contenteditable="true"]');
|
|
107
120
|
var editor = editors[editors.length - 1];
|
|
108
121
|
if (!editor) return { ok: false, reason: 'content editor not found' };
|
|
109
122
|
editor.focus();
|
|
110
123
|
if (editor.querySelector('[contenteditable="false"]')) editor.innerHTML = '';
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
124
|
+
var selection = window.getSelection();
|
|
125
|
+
if (!selection) return { ok: false, reason: 'text selection is unavailable' };
|
|
126
|
+
var range = document.createRange();
|
|
127
|
+
range.selectNodeContents(editor);
|
|
128
|
+
selection.removeAllRanges();
|
|
129
|
+
selection.addRange(range);
|
|
130
|
+
return { ok: false, nativeTargetFocused: true };
|
|
131
|
+
})()`);
|
|
132
|
+
|
|
133
|
+
if (!result?.nativeTargetFocused || typeof page.nativeType !== 'function') return result;
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
await page.nativeType(text);
|
|
137
|
+
} catch {
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return page.evaluate(`(() => {
|
|
114
142
|
var normalize = value => String(value ?? '').replace(/\\r\\n?/g, '\\n').trim();
|
|
115
143
|
var expected = normalize(${JSON.stringify(text)});
|
|
144
|
+
var editors = document.querySelectorAll('div[contenteditable="true"]');
|
|
145
|
+
var editor = editors[editors.length - 1];
|
|
146
|
+
if (!editor) return { ok: false, reason: 'content editor not found' };
|
|
116
147
|
var actual = normalize(editor.innerText ?? editor.textContent ?? '');
|
|
117
148
|
return actual === expected
|
|
118
149
|
? { ok: true, value: actual }
|
|
119
|
-
: { ok: false, reason: '
|
|
150
|
+
: { ok: false, reason: 'editor content verification failed', value: actual };
|
|
120
151
|
})()`);
|
|
121
152
|
}
|
|
122
153
|
|
package/dist/src/errors.d.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* 2 Argument / usage error (ArgumentError)
|
|
15
15
|
* 66 No input / empty result (EmptyResultError)
|
|
16
16
|
* 69 Service unavailable (BrowserConnectError, adapter load failures)
|
|
17
|
-
* 75 Temporary failure, retry later (TimeoutError) EX_TEMPFAIL
|
|
17
|
+
* 75 Temporary failure, retry later (TimeoutError, RateLimitedError) EX_TEMPFAIL
|
|
18
18
|
* 77 Permission denied / auth needed (AuthRequiredError)
|
|
19
19
|
* 78 Configuration error (ConfigError)
|
|
20
20
|
* 130 Interrupted by Ctrl-C (set by tui.ts SIGINT handler)
|
|
@@ -51,6 +51,9 @@ export declare class BrowserConnectError extends CliError {
|
|
|
51
51
|
export declare class CommandExecutionError extends CliError {
|
|
52
52
|
constructor(message: string, hint?: string);
|
|
53
53
|
}
|
|
54
|
+
export declare class RateLimitedError extends CliError {
|
|
55
|
+
constructor(message: string, hint?: string);
|
|
56
|
+
}
|
|
54
57
|
export declare class ConfigError extends CliError {
|
|
55
58
|
constructor(message: string, hint?: string);
|
|
56
59
|
}
|
package/dist/src/errors.js
CHANGED
|
@@ -59,6 +59,11 @@ export class CommandExecutionError extends CliError {
|
|
|
59
59
|
super('COMMAND_EXEC', message, hint, EXIT_CODES.GENERIC_ERROR);
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
+
export class RateLimitedError extends CliError {
|
|
63
|
+
constructor(message, hint) {
|
|
64
|
+
super('RATE_LIMITED', message, hint, EXIT_CODES.TEMPFAIL);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
62
67
|
export class ConfigError extends CliError {
|
|
63
68
|
constructor(message, hint) {
|
|
64
69
|
super('CONFIG', message, hint, EXIT_CODES.CONFIG_ERROR);
|