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.
- package/cli-manifest.json +442 -1
- package/clis/_shared/file-inject.js +41 -0
- package/clis/_shared/video-publish.js +4 -4
- package/clis/bilibili/upload.js +1 -1
- package/clis/chatgpt/utils.js +5 -5
- package/clis/claude/utils.js +1 -1
- package/clis/deepseek/utils.js +7 -7
- package/clis/douyin/draft.js +6 -6
- package/clis/douyin/publish-image.js +10 -31
- package/clis/facebook/feed.js +78 -5
- package/clis/facebook/post.js +9 -36
- package/clis/facebook/search.js +83 -22
- package/clis/instagram/post.js +19 -66
- package/clis/instagram/reel.js +11 -11
- package/clis/threads/post.js +15 -34
- package/clis/twitter/post.js +15 -42
- package/clis/twitter/utils.js +4 -36
- package/clis/wechat-channels/publish.js +29 -57
- package/clis/weibo/publish.js +8 -8
- package/clis/weixin/create-draft.js +7 -7
- package/clis/xianyu/collect.js +1 -0
- package/clis/xianyu/location.js +1 -0
- package/clis/xianyu/manage.js +1 -0
- package/clis/xianyu/mtop.js +47 -0
- package/clis/xianyu/order.js +1 -0
- package/clis/xianyu/publish.js +2 -2
- package/clis/xianyu/rate.js +1 -0
- package/clis/xianyu/user.js +1 -0
- package/clis/xiaohongshu/publish-video.js +9 -27
- package/clis/xiaohongshu/publish.js +32 -72
- package/dist/src/browser/base-page.d.ts +19 -0
- package/dist/src/browser/base-page.js +1 -1
- package/dist/src/browser/bridge-readiness.d.ts +1 -1
- package/dist/src/browser/daemon-client.d.ts +72 -1
- package/dist/src/browser/daemon-client.js +1 -1
- package/dist/src/browser/daemon-version.d.ts +1 -1
- package/dist/src/browser/errors.d.ts +2 -0
- package/dist/src/browser/errors.js +3 -3
- package/dist/src/browser/network-interceptor.d.ts +11 -0
- package/dist/src/browser/network-interceptor.js +1 -0
- package/dist/src/browser/target-resolver.d.ts +1 -0
- package/dist/src/browser/target-resolver.js +100 -6
- package/dist/src/cli.js +24 -24
- package/dist/src/commands/daemon.js +1 -1
- package/dist/src/daemon-utils.d.ts +1 -0
- package/dist/src/daemon-utils.js +1 -1
- package/dist/src/daemon.js +1 -1
- package/dist/src/doctor.d.ts +1 -1
- package/dist/src/doctor.js +7 -7
- package/dist/src/errors.d.ts +8 -0
- package/dist/src/errors.js +1 -1
- package/dist/src/execution.js +2 -2
- package/dist/src/external.js +1 -1
- package/dist/src/session-lease.d.ts +135 -0
- package/dist/src/session-lease.js +1 -0
- package/dist/src/session-lease.test.d.ts +1 -0
- package/dist/src/types.d.ts +3 -0
- 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 (${
|
|
223
|
-
|
|
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
|
-
|
|
227
|
-
|
|
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
|
-
|
|
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
|
(() => {
|