@sovovs/bycli 2.1.52 → 2.1.54
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/clis/weixin/_wechat/user-info.js +146 -75
- package/package.json +1 -1
|
@@ -161,20 +161,79 @@ export const USER_INFO_EXTRACT_SCRIPT = `(() => {
|
|
|
161
161
|
}
|
|
162
162
|
return null;
|
|
163
163
|
};
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
164
|
+
const ignoredValueSelector = [
|
|
165
|
+
'a',
|
|
166
|
+
'button',
|
|
167
|
+
'[role="button"]',
|
|
168
|
+
'[role="tooltip"]',
|
|
169
|
+
'svg',
|
|
170
|
+
'.setting_opr',
|
|
171
|
+
'.weui-desktop-setting__status',
|
|
172
|
+
'.setting_status',
|
|
173
|
+
'.status',
|
|
174
|
+
'.frm_tips',
|
|
175
|
+
'.weui-desktop-form__tips',
|
|
176
|
+
'.weui-desktop-setting__desc',
|
|
177
|
+
'.setting_desc',
|
|
178
|
+
'.tips',
|
|
179
|
+
'.desc',
|
|
180
|
+
'.description',
|
|
181
|
+
'.help',
|
|
182
|
+
'.icon-question',
|
|
183
|
+
'[class*="question"]',
|
|
184
|
+
'[class*="help"]',
|
|
185
|
+
'[class*="popover"]',
|
|
186
|
+
'[class*="-ask"]',
|
|
187
|
+
].join(',');
|
|
188
|
+
const cleanValueText = node => {
|
|
189
|
+
if (!node) return null;
|
|
190
|
+
const copy = node.cloneNode(true);
|
|
191
|
+
copy.querySelectorAll(ignoredValueSelector).forEach(item => item.remove());
|
|
192
|
+
return compact(copy.textContent);
|
|
193
|
+
};
|
|
194
|
+
const primaryValueText = node => {
|
|
195
|
+
if (node && node.matches('.weui-desktop-setting__item__info')) {
|
|
196
|
+
const directText = compact(Array.from(node.childNodes)
|
|
197
|
+
.filter(child => child.nodeType === Node.TEXT_NODE)
|
|
198
|
+
.map(child => child.textContent)
|
|
199
|
+
.join(' '));
|
|
200
|
+
if (directText) return cleanValueText(node);
|
|
201
|
+
const primaryChild = Array.from(node.children)
|
|
202
|
+
.find(child => visible(child) && !child.matches(ignoredValueSelector));
|
|
203
|
+
if (primaryChild) return cleanValueText(primaryChild);
|
|
204
|
+
}
|
|
205
|
+
return cleanValueText(node);
|
|
206
|
+
};
|
|
207
|
+
const textWithout = (node, selector) => {
|
|
208
|
+
if (!node) return null;
|
|
209
|
+
const copy = node.cloneNode(true);
|
|
210
|
+
copy.querySelectorAll(selector).forEach(item => item.remove());
|
|
211
|
+
return compact(copy.textContent);
|
|
212
|
+
};
|
|
213
|
+
const switchValue = row => {
|
|
214
|
+
const node = firstVisible(row, [
|
|
215
|
+
'input[type="checkbox"]',
|
|
216
|
+
'[role="switch"]',
|
|
217
|
+
'.weui-desktop-switch',
|
|
218
|
+
'.weui-switch',
|
|
219
|
+
'[class*="switch"]',
|
|
220
|
+
]);
|
|
221
|
+
if (!node) return null;
|
|
222
|
+
const input = node.matches('input[type="checkbox"]')
|
|
223
|
+
? node
|
|
224
|
+
: node.querySelector('input[type="checkbox"]');
|
|
225
|
+
if (input) return Boolean(input.checked);
|
|
226
|
+
const ariaNode = node.hasAttribute('aria-checked')
|
|
227
|
+
? node
|
|
228
|
+
: node.querySelector('[aria-checked]');
|
|
229
|
+
const ariaChecked = ariaNode && ariaNode.getAttribute('aria-checked');
|
|
230
|
+
if (ariaChecked === 'true') return true;
|
|
231
|
+
if (ariaChecked === 'false') return false;
|
|
232
|
+
const className = [node.className, node.parentElement && node.parentElement.className].join(' ');
|
|
233
|
+
if (/(^|[\\s_-])(checked|on|active)([\\s_-]|$)/i.test(className)) return true;
|
|
234
|
+
if (/(^|[\\s_-])(unchecked|off)([\\s_-]|$)/i.test(className)) return false;
|
|
235
|
+
return null;
|
|
236
|
+
};
|
|
178
237
|
const rowSelectors = [
|
|
179
238
|
'.setting_item',
|
|
180
239
|
'.weui-desktop-setting__item',
|
|
@@ -210,21 +269,55 @@ export const USER_INFO_EXTRACT_SCRIPT = `(() => {
|
|
|
210
269
|
const label = compact(heading && heading.textContent)
|
|
211
270
|
|| compact(sectionNode.getAttribute('aria-label'))
|
|
212
271
|
|| '其他信息';
|
|
272
|
+
const authorizationTable = Array.from(sectionNode.querySelectorAll('table'))
|
|
273
|
+
.filter(visible)
|
|
274
|
+
.find(table => {
|
|
275
|
+
const headers = Array.from(table.querySelectorAll('thead th, tr > th'))
|
|
276
|
+
.filter(visible)
|
|
277
|
+
.map(node => compact(node.textContent));
|
|
278
|
+
return headers.includes('第三方平台名称')
|
|
279
|
+
&& headers.includes('已授权权限')
|
|
280
|
+
&& headers.includes('授权时间');
|
|
281
|
+
}) || null;
|
|
282
|
+
const records = authorizationTable === null ? null : Array.from(
|
|
283
|
+
authorizationTable.querySelectorAll('tbody > tr, tr'),
|
|
284
|
+
).filter(visible).flatMap(row => {
|
|
285
|
+
const cells = Array.from(row.querySelectorAll(':scope > td')).filter(visible);
|
|
286
|
+
if (cells.length < 3 || row.querySelector('.empty_tips')) return [];
|
|
287
|
+
const nameNode = firstVisible(cells[0], [
|
|
288
|
+
'.plugin_info h4',
|
|
289
|
+
'.plugin_info .name',
|
|
290
|
+
'h4',
|
|
291
|
+
]);
|
|
292
|
+
const name = compact(nameNode && nameNode.textContent);
|
|
293
|
+
if (!name) return [];
|
|
294
|
+
const descriptionNode = firstVisible(cells[0], [
|
|
295
|
+
'.plugin_info .desc',
|
|
296
|
+
'.plugin_info p',
|
|
297
|
+
]);
|
|
298
|
+
const permissions = Array.from(cells[1].querySelectorAll('.privilege'))
|
|
299
|
+
.filter(visible)
|
|
300
|
+
.flatMap(node => {
|
|
301
|
+
const permission = textWithout(node, '.dot');
|
|
302
|
+
return permission ? [permission] : [];
|
|
303
|
+
});
|
|
304
|
+
return [{
|
|
305
|
+
name,
|
|
306
|
+
description: compact(descriptionNode && descriptionNode.textContent),
|
|
307
|
+
permissions,
|
|
308
|
+
authorized_at: cleanValueText(cells[2]),
|
|
309
|
+
}];
|
|
310
|
+
});
|
|
213
311
|
let rows = Array.from(sectionNode.querySelectorAll(rowSelector)).filter(visible);
|
|
214
312
|
rows = rows.filter(node => !rows.some(other => other !== node && other.contains(node)));
|
|
215
313
|
const fields = [];
|
|
216
|
-
const actions = [];
|
|
217
314
|
const seenFields = new Set();
|
|
218
|
-
const seenActions = new Set();
|
|
219
315
|
const fieldRows = new Set();
|
|
220
316
|
const genericParts = node => Array.from(node.children).flatMap(child => {
|
|
221
317
|
if (!visible(child)
|
|
222
318
|
|| /^(H1|H2|H3|H4|H5|H6|A|BUTTON)$/.test(child.tagName)
|
|
223
319
|
|| child.getAttribute('role') === 'button') return [];
|
|
224
|
-
const
|
|
225
|
-
copy.querySelectorAll('a, button, [role="button"], svg, .setting_opr, .weui-desktop-setting__status, .setting_status, .status')
|
|
226
|
-
.forEach(item => item.remove());
|
|
227
|
-
const value = compact(copy.textContent);
|
|
320
|
+
const value = cleanValueText(child);
|
|
228
321
|
return value ? [value] : [];
|
|
229
322
|
});
|
|
230
323
|
|
|
@@ -235,56 +328,34 @@ export const USER_INFO_EXTRACT_SCRIPT = `(() => {
|
|
|
235
328
|
const labelNode = firstVisible(row, [
|
|
236
329
|
'.frm_label',
|
|
237
330
|
'.weui-desktop-setting__label',
|
|
331
|
+
'.weui-desktop-setting__item__label',
|
|
238
332
|
'.weui-desktop-form__label',
|
|
239
333
|
'dt',
|
|
240
334
|
'th',
|
|
241
335
|
]);
|
|
242
|
-
const fieldLabel =
|
|
243
|
-
const rowActions = actionNodes(row);
|
|
244
|
-
for (const node of rowActions) {
|
|
245
|
-
const item = action(node);
|
|
246
|
-
const key = JSON.stringify(item);
|
|
247
|
-
if (!seenActions.has(key)) {
|
|
248
|
-
seenActions.add(key);
|
|
249
|
-
actions.push(item);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
336
|
+
const fieldLabel = cleanValueText(labelNode);
|
|
252
337
|
if (!fieldLabel) continue;
|
|
253
338
|
const valueNode = firstVisible(row, [
|
|
254
339
|
'.weui-desktop-setting__value',
|
|
340
|
+
'.weui-desktop-setting__item__info',
|
|
255
341
|
'.setting_value',
|
|
256
342
|
'.frm_value',
|
|
257
343
|
'dd',
|
|
258
344
|
'td',
|
|
259
345
|
'.frm_controls',
|
|
260
346
|
]);
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
'.setting_status',
|
|
264
|
-
'.status',
|
|
265
|
-
]);
|
|
266
|
-
let fieldValue = null;
|
|
267
|
-
let fieldStatus = compact(statusNode && statusNode.textContent);
|
|
268
|
-
if (valueNode) {
|
|
269
|
-
const copy = valueNode.cloneNode(true);
|
|
270
|
-
copy.querySelectorAll('a, button, [role="button"], .setting_opr, .weui-desktop-setting__status, .setting_status, .status')
|
|
271
|
-
.forEach(node => node.remove());
|
|
272
|
-
fieldValue = compact(copy.textContent);
|
|
273
|
-
}
|
|
347
|
+
let fieldValue = switchValue(row);
|
|
348
|
+
if (fieldValue === null) fieldValue = primaryValueText(valueNode);
|
|
274
349
|
if (fieldValue === null) {
|
|
275
350
|
const parts = genericParts(row);
|
|
276
351
|
const labelIndex = parts.indexOf(fieldLabel);
|
|
277
352
|
if (labelIndex !== -1) {
|
|
278
353
|
fieldValue = parts[labelIndex + 1] || null;
|
|
279
|
-
if (fieldStatus === null && parts.length > labelIndex + 2) {
|
|
280
|
-
fieldStatus = parts.slice(labelIndex + 2).join(' ');
|
|
281
|
-
}
|
|
282
354
|
}
|
|
283
355
|
}
|
|
284
356
|
const item = {
|
|
285
357
|
label: fieldLabel,
|
|
286
358
|
value: fieldValue,
|
|
287
|
-
status: fieldStatus,
|
|
288
359
|
};
|
|
289
360
|
const key = JSON.stringify(item);
|
|
290
361
|
if (!seenFields.has(key)) {
|
|
@@ -305,7 +376,6 @@ export const USER_INFO_EXTRACT_SCRIPT = `(() => {
|
|
|
305
376
|
const item = {
|
|
306
377
|
label: parts[0],
|
|
307
378
|
value: parts[1] || null,
|
|
308
|
-
status: parts.length > 2 ? parts.slice(2).join(' ') : null,
|
|
309
379
|
};
|
|
310
380
|
const key = JSON.stringify(item);
|
|
311
381
|
if (!seenFields.has(key)) {
|
|
@@ -314,19 +384,12 @@ export const USER_INFO_EXTRACT_SCRIPT = `(() => {
|
|
|
314
384
|
}
|
|
315
385
|
}
|
|
316
386
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
if (rows.some(row => rowSet.has(row) && row.contains(node))) continue;
|
|
320
|
-
const item = action(node);
|
|
321
|
-
const key = JSON.stringify(item);
|
|
322
|
-
if (!seenActions.has(key)) {
|
|
323
|
-
seenActions.add(key);
|
|
324
|
-
actions.push(item);
|
|
325
|
-
}
|
|
387
|
+
if (fields.length > 0 || (records && records.length > 0)) {
|
|
388
|
+
return [{ label, fields, ...(records === null ? {} : { records }) }];
|
|
326
389
|
}
|
|
327
|
-
if (
|
|
390
|
+
if (records !== null) return [{ label, fields, records, empty: true }];
|
|
328
391
|
const empty = Boolean(sectionNode.querySelector('table thead th, table tr > th'));
|
|
329
|
-
return empty ? [{ label, fields,
|
|
392
|
+
return empty ? [{ label, fields, empty: true }] : [];
|
|
330
393
|
});
|
|
331
394
|
|
|
332
395
|
if (sections.length === 0 && /(无权限|暂无权限|暂不支持|不可用)/.test(document.body.textContent || '')) {
|
|
@@ -342,20 +405,26 @@ function normalizeField(field, tabLabel, sectionIndex, fieldIndex) {
|
|
|
342
405
|
execution(label, prefix);
|
|
343
406
|
return {
|
|
344
407
|
label,
|
|
345
|
-
value: text(field.value),
|
|
346
|
-
status: text(field.status),
|
|
408
|
+
value: typeof field.value === 'boolean' ? field.value : text(field.value),
|
|
347
409
|
};
|
|
348
410
|
}
|
|
349
411
|
|
|
350
|
-
function
|
|
351
|
-
const prefix = `WeChat ${tabLabel} returned an invalid
|
|
352
|
-
execution(object(
|
|
353
|
-
const
|
|
354
|
-
|
|
412
|
+
function normalizeAuthorizationRecord(record, tabLabel, sectionIndex, recordIndex) {
|
|
413
|
+
const prefix = `WeChat ${tabLabel} returned an invalid authorization record at section ${sectionIndex} index ${recordIndex}`;
|
|
414
|
+
execution(object(record), prefix);
|
|
415
|
+
const name = text(record.name);
|
|
416
|
+
const authorizedAt = text(record.authorized_at);
|
|
417
|
+
execution(name && authorizedAt && Array.isArray(record.permissions), prefix);
|
|
418
|
+
const permissions = record.permissions.map((permission, permissionIndex) => {
|
|
419
|
+
const normalized = text(permission);
|
|
420
|
+
execution(normalized, `${prefix} permission ${permissionIndex}`);
|
|
421
|
+
return normalized;
|
|
422
|
+
});
|
|
355
423
|
return {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
424
|
+
name,
|
|
425
|
+
description: text(record.description),
|
|
426
|
+
permissions,
|
|
427
|
+
authorized_at: authorizedAt,
|
|
359
428
|
};
|
|
360
429
|
}
|
|
361
430
|
|
|
@@ -375,16 +444,18 @@ export function normalizeUserInfoTab(tabId, payload) {
|
|
|
375
444
|
const label = text(section.label);
|
|
376
445
|
execution(label, prefix);
|
|
377
446
|
const rawFields = section.fields ?? [];
|
|
378
|
-
|
|
379
|
-
execution(Array.isArray(rawFields) && Array.isArray(rawActions), prefix);
|
|
447
|
+
execution(Array.isArray(rawFields), prefix);
|
|
380
448
|
const fields = rawFields.map((field, fieldIndex) => (
|
|
381
449
|
normalizeField(field, definition.label, sectionIndex, fieldIndex)
|
|
382
450
|
));
|
|
383
|
-
const
|
|
384
|
-
|
|
451
|
+
const hasRecords = Object.prototype.hasOwnProperty.call(section, 'records');
|
|
452
|
+
const rawRecords = hasRecords ? section.records : [];
|
|
453
|
+
execution(Array.isArray(rawRecords), prefix);
|
|
454
|
+
const records = rawRecords.map((record, recordIndex) => (
|
|
455
|
+
normalizeAuthorizationRecord(record, definition.label, sectionIndex, recordIndex)
|
|
385
456
|
));
|
|
386
|
-
return fields.length > 0 ||
|
|
387
|
-
? [{ label, fields,
|
|
457
|
+
return fields.length > 0 || records.length > 0 || section.empty === true
|
|
458
|
+
? [{ label, fields, ...(hasRecords ? { records } : {}) }]
|
|
388
459
|
: [];
|
|
389
460
|
});
|
|
390
461
|
|