@gobing-ai/knowledge-kit 0.0.34 → 0.0.35

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.
Files changed (37) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/dist/index.js +1 -1
  3. package/package.json +1 -1
  4. package/plugins/generations/daily-article-gen/dist/index.js +17 -3
  5. package/plugins/generations/daily-article-gen/src/index.ts +32 -3
  6. package/plugins/generations/dailynews-gen/dist/index.js +2 -1
  7. package/plugins/generations/dailynews-gen/src/script-builder.ts +6 -1
  8. package/plugins/generations/gemini-tts/dist/index.js +4 -3
  9. package/plugins/generations/omni-voice-gen/plugin.json +1 -1
  10. package/plugins/generations/voice-gen/dist/index.js +4 -3
  11. package/plugins/generations/voice-gen/src/index.ts +9 -3
  12. package/plugins/kk/plugin.json +1 -1
  13. package/plugins/kk/scripts/daily-stages.ts +296 -39
  14. package/plugins/kk/scripts/kk-workflow-stages.ts +40 -0
  15. package/plugins/kk/skills/content-safety/references/platforms/wechatmp.md +2 -2
  16. package/plugins/kk/skills/content-safety/references/platforms/xiaoyuzhou.md +4 -2
  17. package/plugins/kk/workflows/kk-daily-ai-voice.yaml +32 -7
  18. package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +7 -4
  19. package/plugins/kk/workflows/kk-daily-safety.yaml +1 -1
  20. package/plugins/publishings/infoq-pub/dist/profile-check.js +30336 -0
  21. package/plugins/publishings/infoq-pub/plugin.json +1 -1
  22. package/plugins/publishings/juejin-pub/dist/profile-check.js +30322 -0
  23. package/plugins/publishings/juejin-pub/plugin.json +1 -1
  24. package/plugins/publishings/substack-pub/dist/profile-check.js +30392 -0
  25. package/plugins/publishings/substack-pub/plugin.json +1 -1
  26. package/plugins/publishings/wechatmp-pub/dist/index.js +307 -132
  27. package/plugins/publishings/wechatmp-pub/dist/profile-check.js +30271 -0
  28. package/plugins/publishings/wechatmp-pub/plugin.json +1 -1
  29. package/plugins/publishings/wechatmp-pub/src/enrich.ts +106 -145
  30. package/plugins/publishings/wechatmp-pub/src/flow.ts +283 -42
  31. package/plugins/publishings/wechatmp-pub/src/page.ts +20 -0
  32. package/plugins/publishings/x-pub/dist/profile-check.js +30328 -0
  33. package/plugins/publishings/x-pub/plugin.json +1 -1
  34. package/plugins/publishings/xhs-pub/dist/profile-check.js +30538 -0
  35. package/plugins/publishings/xhs-pub/plugin.json +1 -1
  36. package/plugins/generations/omni-voice-gen/dist/omni-voice-gen-prr8skpb. +0 -2
  37. package/plugins/generations/omni-voice-gen/dist/omni-voice-gen.js +0 -6
@@ -2,7 +2,7 @@
2
2
  "name": "substack-pub",
3
3
  "kind": "publish",
4
4
  "entry": "./dist/index.js",
5
- "check": "./src/profile-check.ts",
5
+ "check": "./dist/profile-check.js",
6
6
  "version": "1.0.0",
7
7
  "description": "Publish plugin for Substack (substack.com): post drafts through the ProseMirror editor via script browser transport (ts-browser-automation)"
8
8
  }
@@ -30318,19 +30318,35 @@ function wrapPlaywrightContext(raw, entryPage) {
30318
30318
  close: () => context2.close()
30319
30319
  };
30320
30320
  }
30321
+ async function waitForVisible(page, selector, timeoutMs, opts = {}) {
30322
+ const visible = await waitUntil(async () => {
30323
+ const found = await trySelectors(page, [selector]).catch(() => ({ found: false, selector: null }));
30324
+ return found.found;
30325
+ }, timeoutMs, POLL_MS);
30326
+ if (visible)
30327
+ return selector;
30328
+ if (opts.required === false)
30329
+ return;
30330
+ throw new Error(`${selector}: not visible within ${timeoutMs}ms`);
30331
+ }
30321
30332
 
30322
30333
  // ../../plugins/publishings/wechatmp-pub/src/enrich.ts
30323
30334
  var DIALOG = ".weui-desktop-dialog:visible";
30324
30335
  var CONFIRM = `${DIALOG} button:has-text("\u786E\u8BA4"), ${DIALOG} button:has-text("\u786E\u5B9A")`;
30325
- var ORIGINAL_SWITCH = ".setting-group__switch.js_edit_ori";
30326
- var TAG_ROW = ".allow_click_opr.js_article_tags_label";
30336
+ var ROW_ORIGINAL = [".setting-group__switch.js_edit_ori", ".js_edit_ori", "text=\u539F\u521B"];
30337
+ var ROW_REWARD = [".setting-group__switch.js_can_reward", ".js_can_reward", "text=\u8D5E\u8D4F"];
30338
+ var ROW_COLLECTION = [".allow_click_opr.js_article_tags_label", "text=\u5408\u96C6"];
30339
+ var ROW_URL = [".allow_click_opr.js_url_checkbox", "text=\u539F\u6587\u94FE\u63A5"];
30340
+ var ROW_CLAIM = ["#js_claim_source_area .frm_checkbox_label", "text=\u521B\u4F5C\u6765\u6E90"];
30341
+ var DIALOG_CONFIRM = CONFIRM;
30327
30342
  var TAG_INPUT = 'input[placeholder*="\u5408\u96C6"]';
30328
- var CLAIM_SOURCE = "#js_claim_source_area .frm_checkbox_label";
30329
- var AUDIO_MENU = "li.js_insertaudio";
30330
- var AUDIO_DIALOG = ".audio_dialog";
30331
- var AUDIO_DIALOG_TIMEOUT_MS = 15000;
30332
- var AUDIO_ROW_RETRIES = 2;
30333
- var AUDIO_ROW_SETTLE_MS = 1200;
30343
+ var REWARD_ACCOUNT = [
30344
+ `${DIALOG} input[placeholder*="\u8D5E\u8D4F"]`,
30345
+ `${DIALOG} input[placeholder*="\u8D26\u6237"]`,
30346
+ `${DIALOG} input.frm_input`
30347
+ ];
30348
+ var URL_INPUT = [`${DIALOG} input[type="url"]`, `${DIALOG} input[placeholder*="\u94FE\u63A5"]`, `${DIALOG} input.frm_input`];
30349
+ var ORIGINAL_DECLARATION = `${DIALOG} :text("\u6587\u5B57\u539F\u521B")`;
30334
30350
  var COLLECTION_SETTLE_MS = 1200;
30335
30351
  var STEP_RETRY_SETTLE_MS = 1000;
30336
30352
  var SWEEP_SETTLE_MS = 400;
@@ -30340,13 +30356,24 @@ async function enrichArticle(page, meta3) {
30340
30356
  const on6 = (key) => meta3[key] === true;
30341
30357
  const sweep = async () => {
30342
30358
  const cancel = await trySelectors(page, ['button:has-text("\u53D6\u6D88")']);
30343
- if (cancel.found)
30344
- await page.locator(cancel.selector ?? "").first().click({ timeout: 2000 }).catch(() => {
30345
- return;
30346
- });
30359
+ if (cancel.found) {
30360
+ try {
30361
+ await page.locator(cancel.selector ?? "").first().click({ timeout: 2000 });
30362
+ } catch {}
30363
+ }
30347
30364
  await page.press?.("Escape");
30348
30365
  await page.waitForTimeout?.(SWEEP_SETTLE_MS);
30349
30366
  };
30367
+ const openRow = async (row, what) => {
30368
+ for (const selector of row) {
30369
+ const found = await trySelectors(page, [selector]);
30370
+ if (found.found) {
30371
+ await clickSelector(page, selector, 8000);
30372
+ return;
30373
+ }
30374
+ }
30375
+ throw new Error(`no ${what} row control among [${row.join(" | ")}]`);
30376
+ };
30350
30377
  const step = async (name, fn) => {
30351
30378
  try {
30352
30379
  await fn();
@@ -30361,126 +30388,81 @@ async function enrichArticle(page, meta3) {
30361
30388
  await sweep();
30362
30389
  }
30363
30390
  };
30391
+ const dialogsClosed = async () => await page.evaluate(`[...document.querySelectorAll('.weui-desktop-dialog')].every((d) => !d.offsetWidth)`) !== false;
30364
30392
  if (on6("original")) {
30365
30393
  await step("\u539F\u521B\u58F0\u660E", async () => {
30366
- await clickSelector(page, ORIGINAL_SWITCH, 1e4);
30367
- await clickSelector(page, `${DIALOG} :text("\u6587\u5B57\u539F\u521B")`, 8000);
30394
+ await openRow(ROW_ORIGINAL, "\u539F\u521B\u58F0\u660E");
30395
+ const declaration = await trySelectors(page, [ORIGINAL_DECLARATION]).catch(() => ({ found: false }));
30396
+ if (declaration.found)
30397
+ await clickSelector(page, ORIGINAL_DECLARATION, 5000);
30398
+ await clickSelector(page, DIALOG_CONFIRM, 8000);
30399
+ });
30400
+ if (!await dialogsClosed())
30401
+ warnings.push("\u539F\u521B\u58F0\u660E: dialog did not close \u2014 check the draft");
30402
+ }
30403
+ if (on6("reward")) {
30404
+ await step("\u8D5E\u8D4F", async () => {
30405
+ await openRow(ROW_REWARD, "\u8D5E\u8D4F");
30368
30406
  const author = str("author");
30369
- if (author !== "")
30370
- await fillSelector(page, `${DIALOG} input[placeholder*="\u4F5C\u8005"]`, author);
30371
- await clickSelector(page, CONFIRM, 8000);
30407
+ if (author !== "") {
30408
+ for (const selector of REWARD_ACCOUNT) {
30409
+ const found = await trySelectors(page, [selector]).catch(() => ({ found: false, selector: null }));
30410
+ if (!found.found)
30411
+ continue;
30412
+ const empty = await page.evaluate(`(() => { const el = document.querySelector(${JSON.stringify(selector)}); return !el || (el.value ?? '').trim() === ''; })()`);
30413
+ if (empty === true)
30414
+ await fillSelector(page, selector, author);
30415
+ break;
30416
+ }
30417
+ }
30418
+ await clickSelector(page, DIALOG_CONFIRM, 8000);
30372
30419
  });
30373
- const committed = await page.evaluate(`[...document.querySelectorAll('.weui-desktop-dialog')].every((d) => !d.offsetWidth)`);
30374
- if (committed === false) {
30375
- warnings.push("\u539F\u521B\u58F0\u660E: \u672A\u751F\u6548 - \u4F5C\u8005\u987B\u4E3A\u8D5E\u8D4F\u8D26\u6237(\u641C\u7D22\u9009\u62E9)\uFF0C\u8BF7\u624B\u52A8\u8BBE\u7F6E");
30376
- await sweep();
30377
- }
30420
+ if (!await dialogsClosed())
30421
+ warnings.push("\u8D5E\u8D4F: dialog did not close \u2014 check the draft");
30378
30422
  }
30379
30423
  const collection = str("collection");
30380
30424
  if (collection !== "") {
30381
30425
  await step("\u5408\u96C6", async () => {
30382
- await clickSelector(page, TAG_ROW, 8000);
30426
+ await openRow(ROW_COLLECTION, "\u5408\u96C6");
30383
30427
  await waitForVisible(page, TAG_INPUT, 8000);
30384
30428
  await fillSelector(page, TAG_INPUT, collection);
30385
30429
  await page.waitForTimeout?.(COLLECTION_SETTLE_MS);
30386
30430
  await clickSelector(page, `${DIALOG} :text("${collection}")`, 8000);
30387
- await clickSelector(page, CONFIRM, 8000);
30431
+ await clickSelector(page, DIALOG_CONFIRM, 8000);
30432
+ });
30433
+ if (!await dialogsClosed())
30434
+ warnings.push("\u5408\u96C6: dialog did not close \u2014 check the draft");
30435
+ }
30436
+ const originalUrl = str("originalUrl");
30437
+ if (originalUrl !== "") {
30438
+ await step("\u539F\u6587\u94FE\u63A5", async () => {
30439
+ await openRow(ROW_URL, "\u539F\u6587\u94FE\u63A5");
30440
+ const field = await trySelectors(page, URL_INPUT);
30441
+ if (!field.found)
30442
+ throw new Error("no URL field in the \u539F\u6587\u94FE\u63A5 dialog");
30443
+ await fillSelector(page, field.selector ?? URL_INPUT.join(", "), originalUrl);
30444
+ await clickSelector(page, DIALOG_CONFIRM, 8000);
30388
30445
  });
30446
+ if (!await dialogsClosed())
30447
+ warnings.push("\u539F\u6587\u94FE\u63A5: dialog did not close \u2014 check the draft");
30389
30448
  }
30390
- if (on6("aiGenerated")) {
30449
+ const claimSource = str("claimSource");
30450
+ if (claimSource !== "") {
30391
30451
  await step("\u521B\u4F5C\u6765\u6E90", async () => {
30392
- await clickSelector(page, CLAIM_SOURCE, 8000);
30452
+ await openRow(ROW_CLAIM, "\u521B\u4F5C\u6765\u6E90");
30393
30453
  const dialog = await waitForVisible(page, DIALOG, 3000, { required: false });
30394
30454
  if (dialog !== undefined) {
30395
- await clickSelector(page, `${DIALOG} :text("\u5185\u5BB9\u7531AI\u751F\u6210")`, 8000);
30396
- await clickSelector(page, CONFIRM, 8000);
30455
+ await clickSelector(page, `${DIALOG} :text("${claimSource}")`, 8000);
30456
+ await clickSelector(page, DIALOG_CONFIRM, 8000);
30397
30457
  }
30398
30458
  });
30399
30459
  const checked = await page.evaluate(`!!document.querySelector('#js_claim_source_area input:checked')`);
30400
30460
  if (checked === false)
30401
- warnings.push("\u521B\u4F5C\u6765\u6E90: \u52FE\u9009\u672A\u751F\u6548\uFF0C\u8BF7\u624B\u52A8\u8BBE\u7F6E");
30461
+ warnings.push("\u521B\u4F5C\u6765\u6E90: \u672A\u751F\u6548\uFF0C\u8BF7\u624B\u52A8\u8BBE\u7F6E");
30402
30462
  }
30403
30463
  await sweep();
30404
30464
  return warnings;
30405
30465
  }
30406
- async function insertAudio(page, title) {
30407
- const CARET = `(() => {
30408
- const pm = [...document.querySelectorAll('.ProseMirror')].find((e) => !(e.getAttribute('data-placeholder') ?? '').includes('\u6807\u9898'));
30409
- if (!pm || !pm.firstChild) return;
30410
- const r = document.createRange();
30411
- r.setStart(pm.firstChild, 0);
30412
- r.collapse(true);
30413
- const sel = window.getSelection();
30414
- sel?.removeAllRanges();
30415
- sel?.addRange(r);
30416
- })()`;
30417
- const DEDUPE = `(() => {
30418
- const want = ${JSON.stringify(title)}.replace(/\\s+/g, '');
30419
- const hit = [...document.querySelectorAll('label.frm_checkbox_label.audio_item')]
30420
- .find((l) => (l.textContent ?? '').replace(/\\s+/g, '').includes(want));
30421
- if (!hit) return 'missing';
30422
- const cb = (hit.closest('li') ?? hit.parentElement)?.querySelector('input[type=checkbox]');
30423
- if (!cb) return 'nobox';
30424
- cb.click();
30425
- return 'checked';
30426
- })()`;
30427
- const INSERT = `(() => {
30428
- const btn = [...document.querySelectorAll('button')].find((b) => (b.textContent ?? '').trim() === '\u63D2\u5165' && b.offsetWidth > 0);
30429
- if (!btn) return false;
30430
- btn.click();
30431
- return true;
30432
- })()`;
30433
- const CANCEL = `(() => {
30434
- const btn = [...document.querySelectorAll('button')].find((b) => (b.textContent ?? '').trim() === '\u53D6\u6D88' && b.offsetWidth > 0);
30435
- btn?.click();
30436
- })()`;
30437
- const VERIFY = `(() => {
30438
- const pm = [...document.querySelectorAll('.ProseMirror')].find((e) => !(e.getAttribute('data-placeholder') ?? '').includes('\u6807\u9898'));
30439
- if (!pm) return 'noeditor';
30440
- const node = pm.querySelector('mpvoice, [class*="audio"]');
30441
- if (!node) return 'absent';
30442
- const first = pm.firstElementChild;
30443
- return first && (first === node || first.contains(node)) ? 'top' : 'notop';
30444
- })()`;
30445
- try {
30446
- await page.evaluate(CARET);
30447
- await page.evaluate(`document.querySelector(${JSON.stringify(AUDIO_MENU)})?.click()`);
30448
- await waitForVisible(page, AUDIO_DIALOG, AUDIO_DIALOG_TIMEOUT_MS);
30449
- let dedupe = String(await page.evaluate(DEDUPE));
30450
- for (let i2 = 0;dedupe === "missing" && i2 < AUDIO_ROW_RETRIES; i2 += 1) {
30451
- await page.waitForTimeout?.(AUDIO_ROW_SETTLE_MS);
30452
- dedupe = String(await page.evaluate(DEDUPE));
30453
- }
30454
- if (dedupe !== "checked") {
30455
- await page.evaluate(CANCEL);
30456
- return dedupe === "missing" ? "\u97F3\u9891: \u7D20\u6750\u5E93\u65E0\u540C\u540D\u97F3\u9891\uFF0C\u8BF7\u624B\u52A8\u4E0A\u4F20\u540E\u63D2\u5165" : "\u97F3\u9891: \u540C\u540D\u7D20\u6750\u884C\u672A\u627E\u5230\u52FE\u9009\u6846\uFF0C\u8BF7\u624B\u52A8\u63D2\u5165";
30457
- }
30458
- if (await page.evaluate(INSERT) !== true) {
30459
- await page.evaluate(CANCEL);
30460
- return "\u97F3\u9891: \u63D2\u5165\u6309\u94AE\u672A\u627E\u5230\uFF0C\u8BF7\u624B\u52A8\u63D2\u5165";
30461
- }
30462
- await page.waitForTimeout?.(2000);
30463
- const state = String(await page.evaluate(VERIFY));
30464
- if (state === "absent" || state === "noeditor")
30465
- return "\u97F3\u9891: \u63D2\u5165\u672A\u751F\u6548\uFF0C\u8BF7\u624B\u52A8\u68C0\u67E5";
30466
- if (state === "notop")
30467
- return "\u97F3\u9891: \u5DF2\u63D2\u5165\u4F46\u672A\u5728\u6587\u9996\uFF0C\u8BF7\u624B\u52A8\u8C03\u6574\u4F4D\u7F6E";
30468
- return "";
30469
- } catch {
30470
- return "\u97F3\u9891: \u81EA\u52A8\u63D2\u5165\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u63D2\u5165";
30471
- }
30472
- }
30473
- async function waitForVisible(page, selector, timeoutMs, opts = {}) {
30474
- const visible = await waitUntil(async () => {
30475
- const found = await trySelectors(page, [selector]).catch(() => ({ found: false, selector: null }));
30476
- return found.found;
30477
- }, timeoutMs, POLL_MS);
30478
- if (visible)
30479
- return selector;
30480
- if (opts.required === false)
30481
- return;
30482
- throw new Error(`${selector}: not visible within ${timeoutMs}ms`);
30483
- }
30484
30466
 
30485
30467
  // ../../plugins/publishings/wechatmp-pub/src/modes.ts
30486
30468
  import { isAbsolute } from "path";
@@ -30755,11 +30737,15 @@ var LAYOUT_CONTROL = ['button:has-text("\u4E00\u952E\u6392\u7248")', "div.ailayo
30755
30737
  var LAYOUT_TARGET = ['div[role="menuitem"]:has-text("\u5339\u914D\u76EE\u6807\u683C\u5F0F")', 'li:has-text("\u5339\u914D\u76EE\u6807\u683C\u5F0F")'];
30756
30738
  var COVER_PANEL_OPEN = ["a.js_selectCoverFromContent", ".js_cover_btn_area", "text=\u6362\u4E00\u5F20", "text=\u4FEE\u6539"];
30757
30739
  var COVER_FROM_CONTENT = ["a.js_selectCoverFromContent", "text=\u4ECE\u6B63\u6587\u9009\u62E9"];
30758
- var COVER_ITEM = [
30759
- 'div[class*="cover" i] li',
30740
+ var COVER_FROM_LIBRARY = ["a.js_imagedialog", "text=\u4ECE\u56FE\u7247\u5E93\u9009\u62E9"];
30741
+ var COVER_LIBRARY_ITEM = [
30742
+ "div.weui-desktop-img-picker__item",
30743
+ 'div[class*="img_picker" i] li',
30760
30744
  'div[class*="imgList" i] li',
30761
- 'div[class*="weui-desktop-img-picker" i] li'
30745
+ 'div[class*="cover" i] li'
30762
30746
  ];
30747
+ var COVER_LIBRARY_NEXT = ['button:has-text("\u4E0B\u4E00\u6B65")'];
30748
+ var COVER_ITEM = COVER_LIBRARY_ITEM;
30763
30749
  var COVER_CONFIRM = ['button:has-text("\u786E\u5B9A")', 'button:has-text("\u786E\u8BA4")', 'button:has-text("\u5B8C\u6210")'];
30764
30750
  var VIDEO_LOCAL_UPLOAD = ["text=\u672C\u5730\u4E0A\u4F20", 'button:has-text("\u672C\u5730\u4E0A\u4F20")'];
30765
30751
  var VIDEO_FILE_INPUT = [
@@ -30782,6 +30768,30 @@ var PODCAST_COVER_INPUT = [
30782
30768
  'div.weui-desktop-dialog input[type="file"][accept*=".jpg"]'
30783
30769
  ];
30784
30770
  var PODCAST_INSERT = ['div.weui-desktop-dialog button:has-text("\u63D2\u5165")', 'button:has-text("\u63D2\u5165")'];
30771
+ var AUDIO_MENU = "li.js_insertaudio";
30772
+ var AUDIO_DIALOG = ".audio_dialog";
30773
+ var AUDIO_DIALOG_TIMEOUT_MS = 15000;
30774
+ var AUDIO_ROW_RETRIES = 2;
30775
+ var AUDIO_ROW_SETTLE_MS = 1200;
30776
+ var UPLOAD_AUDIO = ["text=\u4E0A\u4F20\u97F3\u9891", 'button:has-text("\u4E0A\u4F20\u97F3\u9891")'];
30777
+ var AUDIO_UPLOAD_INPUT = [
30778
+ '.weui-desktop-dialog input[type="file"][accept*="audio"]',
30779
+ '.weui-desktop-dialog input[type="file"][accept*=".mp3"]',
30780
+ '.audio_dialog input[type="file"][accept*="audio"]',
30781
+ 'input[type="file"][accept*=".mp3"]'
30782
+ ];
30783
+ var UPLOAD_COVER = ["text=\u4E0A\u4F20\u5C01\u9762", 'button:has-text("\u4E0A\u4F20\u5C01\u9762")'];
30784
+ var AUDIO_COVER_INPUT = [
30785
+ '.weui-desktop-dialog input[type="file"][accept*="image/"]',
30786
+ '.audio_dialog input[type="file"][accept*="image/"]',
30787
+ 'input[type="file"][accept*=".png"]'
30788
+ ];
30789
+ var AUDIO_TITLE_INPUT = [
30790
+ '.weui-desktop-dialog input[placeholder*="\u6807\u9898"]',
30791
+ '.audio_dialog input[placeholder*="\u6807\u9898"]',
30792
+ ".audio_dialog input.frm_input"
30793
+ ];
30794
+ var UPLOAD_SAVE = ['.weui-desktop-dialog button:has-text("\u4FDD\u5B58")', 'button:has-text("\u4FDD\u5B58")'];
30785
30795
  var SAVE_DRAFT = ['button:has-text("\u4FDD\u5B58\u4E3A\u8349\u7A3F")', "text=\u4FDD\u5B58\u4E3A\u8349\u7A3F"];
30786
30796
  var PUBLISH_SEND = ["button.mass_send", ".mass_send", 'button:has-text("\u53D1\u8868")'];
30787
30797
  var PUBLISH_CONFIRM = ['div.weui-desktop-dialog button:has-text("\u786E\u5B9A")', 'button:has-text("\u786E\u5B9A")'];
@@ -30953,13 +30963,27 @@ async function insertBody(page, deps) {
30953
30963
  await pasteHtml(asPlaywrightPage(page), selector, markdownToWechatHtml(body), { timeoutMs: deps.stepTimeoutMs });
30954
30964
  }
30955
30965
  async function applyLayout(page, deps) {
30966
+ let control;
30967
+ try {
30968
+ control = await findSelector(page, LAYOUT_CONTROL, "\u4E00\u952E\u6392\u7248 control", deps.stepTimeoutMs);
30969
+ } catch (error51) {
30970
+ return `\u4E00\u952E\u6392\u7248: ${error51 instanceof Error ? error51.message : String(error51)}`;
30971
+ }
30956
30972
  try {
30957
- const control = await findSelector(page, LAYOUT_CONTROL, "\u4E00\u952E\u6392\u7248 control", deps.stepTimeoutMs);
30958
30973
  await clickSelector(page, control, deps.stepTimeoutMs);
30959
- const option = await findSelector(page, LAYOUT_TARGET, "\u5339\u914D\u76EE\u6807\u683C\u5F0F option", 1500).catch(() => null);
30960
- if (option !== null)
30961
- await clickSelector(page, option, 1500);
30962
- } catch {}
30974
+ } catch (error51) {
30975
+ return `\u4E00\u952E\u6392\u7248: click failed \u2014 ${error51 instanceof Error ? error51.message : String(error51)}`;
30976
+ }
30977
+ const option = await tryFindSelector(page, LAYOUT_TARGET, 5000);
30978
+ if (option === undefined) {
30979
+ return "\u4E00\u952E\u6392\u7248: clicked, but no \u5339\u914D\u76EE\u6807\u683C\u5F0F option appeared \u2014 the body may be unformatted; check the draft";
30980
+ }
30981
+ try {
30982
+ await clickSelector(page, option, 5000);
30983
+ return null;
30984
+ } catch (error51) {
30985
+ return `\u4E00\u952E\u6392\u7248: \u5339\u914D\u76EE\u6807\u683C\u5F0F not applied \u2014 ${error51 instanceof Error ? error51.message : String(error51)}`;
30986
+ }
30963
30987
  }
30964
30988
  async function fillOptional(page, selectors, value, what, deps) {
30965
30989
  if (value.length === 0)
@@ -30974,21 +30998,26 @@ async function fillOptional(page, selectors, value, what, deps) {
30974
30998
  return `optional field '${what}': ${error51 instanceof Error ? error51.message : String(error51)}`;
30975
30999
  }
30976
31000
  }
30977
- async function setCoverFromBody(page, deps) {
30978
- const open = await tryFindSelector(page, COVER_PANEL_OPEN, Math.min(deps.stepTimeoutMs, 5000));
30979
- if (open === undefined)
30980
- return "cover: the panel offers neither \u4ECE\u6B63\u6587\u9009\u62E9 nor its openers \u2014 the platform default (\u9ED8\u8BA4\u9996\u56FE\u4E3A\u5C01\u9762) is all this run has";
31001
+ async function setCover(page, source, deps) {
31002
+ const picker = source === "library" ? COVER_FROM_LIBRARY : COVER_FROM_CONTENT;
31003
+ const what = source === "library" ? "\u4ECE\u56FE\u7247\u5E93\u9009\u62E9" : "\u4ECE\u6B63\u6587\u9009\u62E9";
30981
31004
  try {
31005
+ const open = await tryFindSelector(page, COVER_PANEL_OPEN, Math.min(deps.stepTimeoutMs, 5000));
31006
+ if (open === undefined)
31007
+ return "cover: the panel offers none of \u4ECE\u6B63\u6587\u9009\u62E9 / \u4ECE\u56FE\u7247\u5E93\u9009\u62E9 \u2014 the platform default (\u9ED8\u8BA4\u9996\u56FE\u4E3A\u5C01\u9762) is all this run has";
30982
31008
  await clickSelector(page, open, deps.stepTimeoutMs);
30983
- const pick2 = await tryFindSelector(page, COVER_FROM_CONTENT, Math.min(deps.stepTimeoutMs, 5000));
31009
+ const pick2 = await tryFindSelector(page, picker, Math.min(deps.stepTimeoutMs, 8000));
30984
31010
  if (pick2 === undefined)
30985
- return "cover: \u4ECE\u6B63\u6587\u9009\u62E9 was not offered by the open cover panel";
31011
+ return `cover: ${what} was not offered by the open cover panel`;
30986
31012
  await clickSelector(page, pick2, deps.stepTimeoutMs);
30987
- const item = await tryFindSelector(page, COVER_ITEM, Math.min(deps.stepTimeoutMs, 5000));
31013
+ const item = await tryFindSelector(page, COVER_ITEM, Math.min(deps.stepTimeoutMs, 8000));
30988
31014
  if (item === undefined)
30989
- return "cover: the panel listed no body image to choose (its list is not <img>-based, \xA75.2)";
31015
+ return `cover: ${what} listed no image to choose (its list is not <img>-based, \xA75.2)`;
30990
31016
  await clickSelector(page, item, deps.stepTimeoutMs);
30991
- const confirm = await tryFindSelector(page, COVER_CONFIRM, Math.min(deps.stepTimeoutMs, 5000));
31017
+ const next = await tryFindSelector(page, COVER_LIBRARY_NEXT, Math.min(deps.stepTimeoutMs, 4000));
31018
+ if (next !== undefined)
31019
+ await clickSelector(page, next, deps.stepTimeoutMs);
31020
+ const confirm = await tryFindSelector(page, COVER_CONFIRM, Math.min(deps.stepTimeoutMs, 8000));
30992
31021
  if (confirm === undefined)
30993
31022
  return "cover: the choice panel offered no confirm control";
30994
31023
  await clickSelector(page, confirm, deps.stepTimeoutMs);
@@ -30997,14 +31026,27 @@ async function setCoverFromBody(page, deps) {
30997
31026
  return `cover: ${error51 instanceof Error ? error51.message : String(error51)}`;
30998
31027
  }
30999
31028
  }
31029
+ function coverSourceOf(content) {
31030
+ const meta3 = content.metadata?.wechatmp;
31031
+ if (meta3 === null || typeof meta3 !== "object" || Array.isArray(meta3))
31032
+ return "library";
31033
+ return meta3.coverSource === "body" ? "body" : "library";
31034
+ }
31000
31035
  async function enrichArticleDraft(page, content) {
31001
31036
  const enrichMeta = content.metadata?.wechatmp;
31002
31037
  if (enrichMeta === undefined || typeof enrichMeta !== "object" || Array.isArray(enrichMeta))
31003
31038
  return [];
31004
- const warnings = await enrichArticle(page, enrichMeta);
31005
- const audioTitle = enrichMeta.audioTitle;
31006
- if (typeof audioTitle === "string" && audioTitle.trim() !== "") {
31007
- const audioWarning = await insertAudio(page, audioTitle.trim());
31039
+ const meta3 = enrichMeta;
31040
+ const warnings = await enrichArticle(page, meta3);
31041
+ const audioTitle = meta3.audioTitle;
31042
+ const audioPath = meta3.audioPath;
31043
+ const audioCoverPath = meta3.audioCoverPath;
31044
+ if (typeof audioTitle === "string" && audioTitle.trim() !== "" && typeof audioPath === "string" && audioPath !== "") {
31045
+ const audioWarning = await insertAudioMaterial(page, {
31046
+ title: audioTitle.trim(),
31047
+ audioPath,
31048
+ coverPath: typeof audioCoverPath === "string" ? audioCoverPath : ""
31049
+ });
31008
31050
  if (audioWarning !== "")
31009
31051
  warnings.push(audioWarning);
31010
31052
  }
@@ -31016,7 +31058,9 @@ async function composeArticle(input, deps, entry) {
31016
31058
  await attachImages(page, input.images, deps);
31017
31059
  const titlePath = await typeTitle(page, deps);
31018
31060
  await insertBody(page, deps);
31019
- await applyLayout(page, deps);
31061
+ const layout = await applyLayout(page, deps);
31062
+ if (layout !== null)
31063
+ warnings.push(layout);
31020
31064
  for (const warning of [
31021
31065
  await fillOptional(page, DIGEST_INPUT, input.digest ?? "", "\u6458\u8981", deps),
31022
31066
  await fillOptional(page, AUTHOR_INPUT, authorOf(deps.content), "\u4F5C\u8005", deps)
@@ -31024,7 +31068,7 @@ async function composeArticle(input, deps, entry) {
31024
31068
  if (warning !== null)
31025
31069
  warnings.push(warning);
31026
31070
  }
31027
- const cover = await setCoverFromBody(page, deps);
31071
+ const cover = await setCover(page, coverSourceOf(deps.content), deps);
31028
31072
  if (cover !== null)
31029
31073
  warnings.push(cover);
31030
31074
  return { warnings, titlePath, enrichWarnings: await enrichArticleDraft(page, deps.content) };
@@ -31080,8 +31124,12 @@ async function compose(input, deps, entry) {
31080
31124
  }
31081
31125
  }
31082
31126
  function authorOf(content) {
31083
- const author = content.metadata?.author;
31084
- return typeof author === "string" ? author : "";
31127
+ const wechatmp = content.metadata?.wechatmp;
31128
+ const scoped = wechatmp !== null && typeof wechatmp === "object" && !Array.isArray(wechatmp) ? wechatmp.author : undefined;
31129
+ const generic = content.metadata?.author;
31130
+ if (typeof generic === "string" && generic.trim() !== "")
31131
+ return generic.trim();
31132
+ return typeof scoped === "string" ? scoped.trim() : "";
31085
31133
  }
31086
31134
  function baseMetadata(input, deps, entry) {
31087
31135
  const cover = coverPath(input);
@@ -31262,6 +31310,133 @@ function markdownToWechatHtml(markdown) {
31262
31310
  function escapeHtml(text) {
31263
31311
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
31264
31312
  }
31313
+ async function insertAudioMaterial(page, input) {
31314
+ const { title, audioPath, coverPath: coverPath2 } = input;
31315
+ const CARET = `(() => {
31316
+ const pm = [...document.querySelectorAll('.ProseMirror')].find((e) => !(e.getAttribute('data-placeholder') ?? '').includes('\u6807\u9898'));
31317
+ if (!pm || !pm.firstChild) return;
31318
+ const r = document.createRange();
31319
+ r.setStart(pm.firstChild, 0);
31320
+ r.collapse(true);
31321
+ const sel = window.getSelection();
31322
+ sel?.removeAllRanges();
31323
+ sel?.addRange(r);
31324
+ })()`;
31325
+ const DEDUPE = `(() => {
31326
+ const want = ${JSON.stringify(title)}.replace(/\\s+/g, '');
31327
+ const hit = [...document.querySelectorAll('label.frm_checkbox_label.audio_item')]
31328
+ .find((l) => (l.textContent ?? '').replace(/\\s+/g, '').includes(want));
31329
+ if (!hit) return 'missing';
31330
+ const cb = (hit.closest('li') ?? hit.parentElement)?.querySelector('input[type=checkbox]');
31331
+ if (!cb) return 'nobox';
31332
+ cb.click();
31333
+ return 'checked';
31334
+ })()`;
31335
+ const AGREE = `(() => {
31336
+ const node = [...document.querySelectorAll('label, span, div')]
31337
+ .find((e) => (e.textContent ?? '').includes('\u6211\u5DF2\u9605\u8BFB\u5E76\u540C\u610F') && e.children.length === 0);
31338
+ if (!node) return 'no-label';
31339
+ const scope = node.closest('label') ?? node.parentElement;
31340
+ const cb = scope?.querySelector('input[type=checkbox]') ?? document.querySelector('input[type=checkbox].js_agree');
31341
+ if (!cb) return 'no-box';
31342
+ if (!cb.checked) cb.click();
31343
+ return cb.checked ? 'checked' : 'unchecked';
31344
+ })()`;
31345
+ const SELECT_FIRST = `(() => {
31346
+ const row = document.querySelector('label.frm_checkbox_label.audio_item');
31347
+ if (!row) return 'norow';
31348
+ const cb = (row.closest('li') ?? row.parentElement)?.querySelector('input[type=checkbox]');
31349
+ if (!cb) return 'nobox';
31350
+ if (!cb.checked) cb.click();
31351
+ return 'checked';
31352
+ })()`;
31353
+ const INSERT = `(() => {
31354
+ const btn = [...document.querySelectorAll('button')].find((b) => (b.textContent ?? '').trim() === '\u63D2\u5165' && b.offsetWidth > 0);
31355
+ if (!btn) return false;
31356
+ btn.click();
31357
+ return true;
31358
+ })()`;
31359
+ const CANCEL = `(() => {
31360
+ const btn = [...document.querySelectorAll('button')].find((b) => (b.textContent ?? '').trim() === '\u53D6\u6D88' && b.offsetWidth > 0);
31361
+ btn?.click();
31362
+ })()`;
31363
+ const VERIFY = `(() => {
31364
+ const pm = [...document.querySelectorAll('.ProseMirror')].find((e) => !(e.getAttribute('data-placeholder') ?? '').includes('\u6807\u9898'));
31365
+ if (!pm) return 'noeditor';
31366
+ const node = pm.querySelector('mpvoice, [class*="audio"]');
31367
+ if (!node) return 'absent';
31368
+ const first = pm.firstElementChild;
31369
+ return first && (first === node || first.contains(node)) ? 'top' : 'notop';
31370
+ })()`;
31371
+ const upload = async () => {
31372
+ const uploadControl = await trySelectors(page, UPLOAD_AUDIO);
31373
+ if (!uploadControl.found)
31374
+ return "\u97F3\u9891: \u4E0A\u4F20\u97F3\u9891 control not found in the audio dialog";
31375
+ await clickSelector(page, UPLOAD_AUDIO.join(", "), 8000);
31376
+ const audioInput = await trySelectors(page, AUDIO_UPLOAD_INPUT);
31377
+ if (!audioInput.found)
31378
+ return "\u97F3\u9891: no audio file input appeared";
31379
+ await uploadFile(asPlaywrightPage(page), audioInput.selector ?? AUDIO_UPLOAD_INPUT.join(", "), audioPath, {
31380
+ timeoutMs: 60000
31381
+ });
31382
+ const coverControl = await trySelectors(page, UPLOAD_COVER);
31383
+ if (coverControl.found) {
31384
+ await clickSelector(page, UPLOAD_COVER.join(", "), 8000);
31385
+ const coverInput = await trySelectors(page, AUDIO_COVER_INPUT);
31386
+ if (coverInput.found)
31387
+ await uploadFile(asPlaywrightPage(page), coverInput.selector ?? AUDIO_COVER_INPUT.join(", "), coverPath2, {
31388
+ timeoutMs: 60000
31389
+ });
31390
+ }
31391
+ const titleInput = await trySelectors(page, AUDIO_TITLE_INPUT);
31392
+ if (titleInput.found)
31393
+ await fillSelector(page, titleInput.selector ?? AUDIO_TITLE_INPUT.join(", "), title);
31394
+ const agreed = String(await page.evaluate(AGREE));
31395
+ if (agreed !== "checked")
31396
+ return `\u97F3\u9891: \u670D\u52A1\u89C4\u5219\u52FE\u9009\u5931\u8D25 (${agreed})`;
31397
+ const save = await trySelectors(page, UPLOAD_SAVE);
31398
+ if (!save.found)
31399
+ return "\u97F3\u9891: \u4E0A\u4F20\u8868\u5355\u7684\u4FDD\u5B58\u6309\u94AE\u672A\u627E\u5230";
31400
+ await clickSelector(page, UPLOAD_SAVE.join(", "), 8000);
31401
+ return null;
31402
+ };
31403
+ try {
31404
+ await page.evaluate(CARET);
31405
+ await page.evaluate(`document.querySelector(${JSON.stringify(AUDIO_MENU)})?.click()`);
31406
+ await waitForVisible(page, AUDIO_DIALOG, AUDIO_DIALOG_TIMEOUT_MS);
31407
+ let dedupe = String(await page.evaluate(DEDUPE));
31408
+ for (let i2 = 0;dedupe === "missing" && i2 < AUDIO_ROW_RETRIES; i2 += 1) {
31409
+ await page.waitForTimeout?.(AUDIO_ROW_SETTLE_MS);
31410
+ dedupe = String(await page.evaluate(DEDUPE));
31411
+ }
31412
+ if (dedupe !== "checked") {
31413
+ const uploadWarning = await upload();
31414
+ if (uploadWarning !== null) {
31415
+ await page.evaluate(CANCEL);
31416
+ return uploadWarning;
31417
+ }
31418
+ await waitForVisible(page, AUDIO_DIALOG, AUDIO_DIALOG_TIMEOUT_MS);
31419
+ const selected = String(await page.evaluate(SELECT_FIRST));
31420
+ if (selected !== "checked") {
31421
+ await page.evaluate(CANCEL);
31422
+ return `\u97F3\u9891: \u4E0A\u4F20\u540E\u672A\u627E\u5230\u7D20\u6750\u884C (${selected})`;
31423
+ }
31424
+ }
31425
+ if (await page.evaluate(INSERT) !== true) {
31426
+ await page.evaluate(CANCEL);
31427
+ return "\u97F3\u9891: \u63D2\u5165\u6309\u94AE\u672A\u627E\u5230\uFF0C\u8BF7\u624B\u52A8\u63D2\u5165";
31428
+ }
31429
+ await page.waitForTimeout?.(2000);
31430
+ const state = String(await page.evaluate(VERIFY));
31431
+ if (state === "absent" || state === "noeditor")
31432
+ return "\u97F3\u9891: \u63D2\u5165\u672A\u751F\u6548\uFF0C\u8BF7\u624B\u52A8\u68C0\u67E5";
31433
+ if (state === "notop")
31434
+ return "\u97F3\u9891: \u5DF2\u63D2\u5165\u4F46\u672A\u5728\u6587\u9996\uFF0C\u8BF7\u624B\u52A8\u8C03\u6574\u4F4D\u7F6E";
31435
+ return "";
31436
+ } catch (error51) {
31437
+ return `\u97F3\u9891: ${error51 instanceof Error ? error51.message.slice(0, 120) : "\u81EA\u52A8\u63D2\u5165\u5931\u8D25"}\uFF0C\u8BF7\u624B\u52A8\u63D2\u5165`;
31438
+ }
31439
+ }
31265
31440
 
31266
31441
  // ../../plugins/publishings/wechatmp-pub/src/index.ts
31267
31442
  var CHANNEL = TARGET;