publishport-opencli 1.0.8 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/cli-manifest.json +442 -1
  2. package/clis/_shared/file-inject.js +41 -0
  3. package/clis/_shared/video-publish.js +4 -4
  4. package/clis/bilibili/upload.js +1 -1
  5. package/clis/chatgpt/utils.js +5 -5
  6. package/clis/claude/utils.js +1 -1
  7. package/clis/deepseek/utils.js +7 -7
  8. package/clis/douyin/draft.js +6 -6
  9. package/clis/douyin/publish-image.js +10 -31
  10. package/clis/facebook/feed.js +78 -5
  11. package/clis/facebook/post.js +9 -36
  12. package/clis/facebook/search.js +83 -22
  13. package/clis/instagram/post.js +19 -66
  14. package/clis/instagram/reel.js +11 -11
  15. package/clis/threads/post.js +15 -34
  16. package/clis/twitter/post.js +15 -42
  17. package/clis/twitter/utils.js +4 -36
  18. package/clis/wechat-channels/publish.js +29 -57
  19. package/clis/weibo/publish.js +8 -8
  20. package/clis/weixin/create-draft.js +7 -7
  21. package/clis/xianyu/collect.js +1 -0
  22. package/clis/xianyu/location.js +1 -0
  23. package/clis/xianyu/manage.js +1 -0
  24. package/clis/xianyu/mtop.js +47 -0
  25. package/clis/xianyu/order.js +1 -0
  26. package/clis/xianyu/publish.js +2 -2
  27. package/clis/xianyu/rate.js +1 -0
  28. package/clis/xianyu/user.js +1 -0
  29. package/clis/xiaohongshu/publish-video.js +9 -27
  30. package/clis/xiaohongshu/publish.js +32 -72
  31. package/dist/src/browser/base-page.d.ts +19 -0
  32. package/dist/src/browser/base-page.js +1 -1
  33. package/dist/src/browser/bridge-readiness.d.ts +1 -1
  34. package/dist/src/browser/daemon-client.d.ts +72 -1
  35. package/dist/src/browser/daemon-client.js +1 -1
  36. package/dist/src/browser/daemon-version.d.ts +1 -1
  37. package/dist/src/browser/errors.d.ts +2 -0
  38. package/dist/src/browser/errors.js +3 -3
  39. package/dist/src/browser/network-interceptor.d.ts +11 -0
  40. package/dist/src/browser/network-interceptor.js +1 -0
  41. package/dist/src/browser/target-resolver.d.ts +1 -0
  42. package/dist/src/browser/target-resolver.js +100 -6
  43. package/dist/src/cli.js +24 -24
  44. package/dist/src/commands/daemon.js +1 -1
  45. package/dist/src/daemon-utils.d.ts +1 -0
  46. package/dist/src/daemon-utils.js +1 -1
  47. package/dist/src/daemon.js +1 -1
  48. package/dist/src/doctor.d.ts +1 -1
  49. package/dist/src/doctor.js +7 -7
  50. package/dist/src/errors.d.ts +8 -0
  51. package/dist/src/errors.js +1 -1
  52. package/dist/src/execution.js +2 -2
  53. package/dist/src/external.js +1 -1
  54. package/dist/src/session-lease.d.ts +135 -0
  55. package/dist/src/session-lease.js +1 -0
  56. package/dist/src/session-lease.test.d.ts +1 -0
  57. package/dist/src/types.d.ts +3 -0
  58. package/package.json +1 -1
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Injected page-side network interceptor.
3
+ *
4
+ * Used when the session-level capture channel (CDP/extension) is unavailable.
5
+ * It captures fetch/XHR response bodies while matching the CDP path's
6
+ * truncation contract: bodies above the per-entry cap are stored as a string
7
+ * prefix with `bodyTruncated: true` and `bodyFullSize` set.
8
+ *
9
+ * Keep this script dependency-free; it executes in the target page context.
10
+ */
11
+ export declare const NETWORK_INTERCEPTOR_JS = "(function(){if(window.__opencli_net)return;window.__opencli_net=[];var M=200,B=1048576,F=window.fetch;function capture(url,method,status,text,ct){if(window.__opencli_net.length>=M)return;var full=text?text.length:0,trunc=full>B,stored=trunc?text.slice(0,B):text,body=null;if(stored){if(trunc){body=stored}else{try{body=JSON.parse(stored)}catch(e){body=stored}}}var e={url:url,method:method||'GET',status:status,size:full,ct:ct,body:body,timestamp:Date.now()};if(trunc){e.bodyTruncated=true;e.bodyFullSize=full}window.__opencli_net.push(e)}window.fetch=async function(){var r=await F.apply(this,arguments);try{var ct=r.headers.get('content-type')||'';if(ct.includes('json')||ct.includes('text')){var c=r.clone(),t=await c.text();capture(r.url||(arguments[0]&&arguments[0].url)||String(arguments[0]),(arguments[1]&&arguments[1].method)||'GET',r.status,t,ct)}}catch(e){}return r};var X=XMLHttpRequest.prototype,O=X.open,S=X.send;X.open=function(m,u){this._om=m;this._ou=u;return O.apply(this,arguments)};X.send=function(){var x=this;x.addEventListener('load',function(){try{var ct=x.getResponseHeader('content-type')||'';if(ct.includes('json')||ct.includes('text')){capture(x._ou,x._om||'GET',x.status,x.responseText||'',ct)}}catch(e){}});return S.apply(this,arguments)}})()";
@@ -0,0 +1 @@
1
+ export const NETWORK_INTERCEPTOR_JS="(function(){if(window.__opencli_net)return;window.__opencli_net=[];var M=200,B=1048576,F=window.fetch;function capture(url,method,status,text,ct){if(window.__opencli_net.length>=M)return;var full=text?text.length:0,trunc=full>B,stored=trunc?text.slice(0,B):text,body=null;if(stored){if(trunc){body=stored}else{try{body=JSON.parse(stored)}catch(e){body=stored}}}var e={url:url,method:method||'GET',status:status,size:full,ct:ct,body:body,timestamp:Date.now()};if(trunc){e.bodyTruncated=true;e.bodyFullSize=full}window.__opencli_net.push(e)}window.fetch=async function(){var r=await F.apply(this,arguments);try{var ct=r.headers.get('content-type')||'';if(ct.includes('json')||ct.includes('text')){var c=r.clone(),t=await c.text();capture(r.url||(arguments[0]&&arguments[0].url)||String(arguments[0]),(arguments[1]&&arguments[1].method)||'GET',r.status,t,ct)}}catch(e){}return r};var X=XMLHttpRequest.prototype,O=X.open,S=X.send;X.open=function(m,u){this._om=m;this._ou=u;return O.apply(this,arguments)};X.send=function(){var x=this;x.addEventListener('load',function(){try{var ct=x.getResponseHeader('content-type')||'';if(ct.includes('json')||ct.includes('text')){capture(x._ou,x._om||'GET',x.status,x.responseText||'',ct)}}catch(e){}});return S.apply(this,arguments)}})()";
@@ -77,6 +77,7 @@ export declare function resolveTargetJs(ref: string, opts?: ResolveOptions): str
77
77
  */
78
78
  export declare function boundingRectResolvedJs(opts?: {
79
79
  skipScroll?: boolean;
80
+ forClick?: boolean;
80
81
  }): string;
81
82
  /**
82
83
  * Generate JS for click that uses the unified resolver.
@@ -215,18 +215,112 @@ export function resolveTargetJs(j,g={}){const q=JSON.stringify(j),w=g.nth!==void
215
215
  return { ok: true, matches_n: matches.length, match_level: 'exact' };
216
216
  }
217
217
  })()
218
- `}export function boundingRectResolvedJs(j={}){return`
218
+ `}export function boundingRectResolvedJs(j={}){const g=j.skipScroll?"false":"true",q=j.forClick?"true":"false";return`
219
219
  (() => {
220
220
  const el = window.__resolved;
221
221
  if (!el) throw new Error('No resolved element');
222
- if (${j.skipScroll?"false":"true"}) el.scrollIntoView({ behavior: 'instant', block: 'center' });
223
- const rect = el.getBoundingClientRect();
222
+ if (${g}) el.scrollIntoView({ behavior: 'instant', block: 'center' });
223
+
224
+ const FOR_CLICK = ${q};
225
+ // hover()/dblClick() want the plain element centre — the retarget + hit-test
226
+ // below are click-only so those actions keep their original behaviour.
227
+ if (!FOR_CLICK) {
228
+ const r0 = el.getBoundingClientRect();
229
+ return {
230
+ x: Math.round(r0.left + r0.width / 2),
231
+ y: Math.round(r0.top + r0.height / 2),
232
+ w: Math.round(r0.width),
233
+ h: Math.round(r0.height),
234
+ visible: Math.round(r0.width) > 0 && Math.round(r0.height) > 0,
235
+ };
236
+ }
237
+
238
+ // Does this node OWN a click handler? Deliberately excludes cursor:pointer,
239
+ // which is an *inherited* CSS property — an <svg> icon inside a clickable
240
+ // <div> inherits the pointer cursor but owns no handler, so cursor can't
241
+ // decide whether a node is the real click target. See issue #2071.
242
+ const ownsClickHandler = (node) => {
243
+ if (!node || node.nodeType !== 1) return false;
244
+ const tag = node.tagName.toLowerCase();
245
+ if (['a','button','input','select','textarea','label','summary'].includes(tag)) return true;
246
+ const role = node.getAttribute && node.getAttribute('role');
247
+ if (role && ['button','link','menuitem','menuitemcheckbox','menuitemradio','tab','option','checkbox','radio','switch'].includes(role)) return true;
248
+ if (typeof node.onclick === 'function') return true;
249
+ if (node.hasAttribute && (node.hasAttribute('onclick') || node.hasAttribute('jsaction'))) return true;
250
+ try {
251
+ for (const k in node) {
252
+ if (k.charCodeAt(0) === 95 && (k.indexOf('__reactProps$') === 0 || k.indexOf('__reactEventHandlers$') === 0)) {
253
+ const p = node[k];
254
+ if (p && (p.onClick || p.onMouseDown || p.onMouseUp)) return true;
255
+ }
256
+ }
257
+ } catch (e) {}
258
+ return false;
259
+ };
260
+ // A retarget destination just needs to look clickable; here cursor:pointer
261
+ // IS a useful signal (the ancestor is where it was set).
262
+ const isClickableAncestor = (node) => {
263
+ if (ownsClickHandler(node)) return true;
264
+ try { return window.getComputedStyle(node).cursor === 'pointer'; } catch (e) { return false; }
265
+ };
266
+
267
+ // #2071: if the resolved node owns no click handler but a nearby ancestor
268
+ // is clickable, aim at that ancestor so the handler fires.
269
+ let target = el;
270
+ let retargeted = false;
271
+ if (!ownsClickHandler(el)) {
272
+ let a = el.parentElement, hops = 0;
273
+ while (a && hops < 4) {
274
+ if (isClickableAncestor(a)) { target = a; retargeted = true; break; }
275
+ a = a.parentElement; hops++;
276
+ }
277
+ }
278
+
279
+ const rect = target.getBoundingClientRect();
224
280
  const w = Math.round(rect.width);
225
281
  const h = Math.round(rect.height);
226
- const x = Math.round(rect.left + rect.width / 2);
227
- const y = Math.round(rect.top + rect.height / 2);
282
+ let x = Math.round(rect.left + rect.width / 2);
283
+ let y = Math.round(rect.top + rect.height / 2);
228
284
  const visible = w > 0 && h > 0;
229
- return { x, y, w, h, visible };
285
+
286
+ // #2076: verify the click point actually lands on the target. A trusted
287
+ // CDP click hit-tests at (x,y) and delivers the event to whatever is
288
+ // topmost there — an overlay/sibling can silently swallow it. Classify:
289
+ // 'target' — the point is the target or a light-DOM descendant.
290
+ // 'ancestor' — the point is an ANCESTOR of the target. This is the
291
+ // open-shadow-DOM case (elementFromPoint returns the shadow
292
+ // *host*, not the shadow content) and the "point sits over
293
+ // the target's own wrapper background" case. In both a CDP
294
+ // click at (x,y) still reaches the target — CDP hit-testing
295
+ // pierces shadow roots, and light-DOM clicks bubble up — so
296
+ // it is trustworthy, unlike an unrelated overlay.
297
+ // 'other' — an unrelated element covers the point (the real overlay
298
+ // bug); the caller then dispatches a direct DOM click.
299
+ const hitClass = (px, py) => {
300
+ let at = null;
301
+ try { at = document.elementFromPoint(px, py); } catch (e) { return 'none'; }
302
+ if (!at) return 'none';
303
+ if (at === target || target.contains(at)) return 'target';
304
+ if (at.contains && at.contains(target)) return 'ancestor';
305
+ return 'other';
306
+ };
307
+ let hit = visible ? hitClass(x, y) : 'none';
308
+ if (visible && hit !== 'target' && hit !== 'ancestor') {
309
+ const cands = [
310
+ [rect.left + rect.width * 0.5, rect.top + rect.height * 0.25],
311
+ [rect.left + rect.width * 0.25, rect.top + rect.height * 0.5],
312
+ [rect.left + rect.width * 0.75, rect.top + rect.height * 0.5],
313
+ [rect.left + rect.width * 0.5, rect.top + rect.height * 0.75],
314
+ [rect.left + 3, rect.top + 3],
315
+ [rect.right - 3, rect.bottom - 3],
316
+ ];
317
+ for (const c of cands) {
318
+ const px = Math.round(c[0]), py = Math.round(c[1]);
319
+ const hc = hitClass(px, py);
320
+ if (hc === 'target' || hc === 'ancestor') { x = px; y = py; hit = hc; break; }
321
+ }
322
+ }
323
+ return { x, y, w, h, visible, hit, retargeted };
230
324
  })()
231
325
  `}export function clickResolvedJs(j={}){return`
232
326
  (() => {