@jackwener/opencli 1.5.0 → 1.5.2
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/dist/browser/cdp.js +5 -0
- package/dist/browser/discover.js +11 -7
- package/dist/browser/index.d.ts +2 -0
- package/dist/browser/index.js +2 -0
- package/dist/browser/page.d.ts +4 -0
- package/dist/browser/page.js +52 -3
- package/dist/browser.test.js +5 -0
- package/dist/cli-manifest.json +460 -1
- package/dist/cli.js +34 -3
- package/dist/clis/apple-podcasts/commands.test.js +26 -3
- package/dist/clis/apple-podcasts/top.js +4 -1
- package/dist/clis/bluesky/feeds.yaml +29 -0
- package/dist/clis/bluesky/followers.yaml +33 -0
- package/dist/clis/bluesky/following.yaml +33 -0
- package/dist/clis/bluesky/profile.yaml +27 -0
- package/dist/clis/bluesky/search.yaml +34 -0
- package/dist/clis/bluesky/starter-packs.yaml +34 -0
- package/dist/clis/bluesky/thread.yaml +32 -0
- package/dist/clis/bluesky/trending.yaml +27 -0
- package/dist/clis/bluesky/user.yaml +34 -0
- package/dist/clis/twitter/trending.js +29 -61
- package/dist/clis/weread/shelf.js +132 -9
- package/dist/clis/weread/utils.js +5 -1
- package/dist/clis/xiaohongshu/publish.js +78 -42
- package/dist/clis/xiaohongshu/publish.test.js +20 -8
- package/dist/clis/xiaohongshu/search.d.ts +8 -1
- package/dist/clis/xiaohongshu/search.js +20 -1
- package/dist/clis/xiaohongshu/search.test.d.ts +1 -1
- package/dist/clis/xiaohongshu/search.test.js +32 -1
- package/dist/daemon.js +1 -0
- package/dist/discovery.js +40 -28
- package/dist/doctor.d.ts +1 -2
- package/dist/doctor.js +9 -5
- package/dist/engine.test.js +42 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +2 -2
- package/dist/execution.js +45 -13
- package/dist/execution.test.d.ts +1 -0
- package/dist/execution.test.js +40 -0
- package/dist/extension-manifest-regression.test.d.ts +1 -0
- package/dist/extension-manifest-regression.test.js +12 -0
- package/dist/external.js +6 -1
- package/dist/main.js +1 -0
- package/dist/plugin-scaffold.d.ts +28 -0
- package/dist/plugin-scaffold.js +142 -0
- package/dist/plugin-scaffold.test.d.ts +4 -0
- package/dist/plugin-scaffold.test.js +83 -0
- package/dist/plugin.d.ts +55 -17
- package/dist/plugin.js +706 -154
- package/dist/plugin.test.js +836 -38
- package/dist/runtime.d.ts +1 -0
- package/dist/runtime.js +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/weread-private-api-regression.test.js +185 -0
- package/docs/adapters/browser/bluesky.md +53 -0
- package/docs/guide/plugins.md +10 -0
- package/extension/dist/background.js +4 -2
- package/extension/manifest.json +4 -1
- package/extension/package-lock.json +2 -2
- package/extension/package.json +1 -1
- package/extension/src/background.ts +2 -1
- package/package.json +1 -1
- package/src/browser/cdp.ts +6 -0
- package/src/browser/discover.ts +10 -7
- package/src/browser/index.ts +2 -0
- package/src/browser/page.ts +49 -3
- package/src/browser.test.ts +6 -0
- package/src/cli.ts +34 -3
- package/src/clis/apple-podcasts/commands.test.ts +30 -2
- package/src/clis/apple-podcasts/top.ts +4 -1
- package/src/clis/bluesky/feeds.yaml +29 -0
- package/src/clis/bluesky/followers.yaml +33 -0
- package/src/clis/bluesky/following.yaml +33 -0
- package/src/clis/bluesky/profile.yaml +27 -0
- package/src/clis/bluesky/search.yaml +34 -0
- package/src/clis/bluesky/starter-packs.yaml +34 -0
- package/src/clis/bluesky/thread.yaml +32 -0
- package/src/clis/bluesky/trending.yaml +27 -0
- package/src/clis/bluesky/user.yaml +34 -0
- package/src/clis/twitter/trending.ts +29 -77
- package/src/clis/weread/shelf.ts +169 -9
- package/src/clis/weread/utils.ts +6 -1
- package/src/clis/xiaohongshu/publish.test.ts +22 -8
- package/src/clis/xiaohongshu/publish.ts +93 -52
- package/src/clis/xiaohongshu/search.test.ts +39 -1
- package/src/clis/xiaohongshu/search.ts +19 -1
- package/src/daemon.ts +1 -0
- package/src/discovery.ts +41 -33
- package/src/doctor.ts +11 -8
- package/src/engine.test.ts +38 -0
- package/src/errors.ts +6 -2
- package/src/execution.test.ts +47 -0
- package/src/execution.ts +39 -15
- package/src/extension-manifest-regression.test.ts +17 -0
- package/src/external.ts +6 -1
- package/src/main.ts +1 -0
- package/src/plugin-scaffold.test.ts +98 -0
- package/src/plugin-scaffold.ts +170 -0
- package/src/plugin.test.ts +881 -38
- package/src/plugin.ts +871 -158
- package/src/runtime.ts +2 -2
- package/src/types.ts +2 -0
- package/src/weread-private-api-regression.test.ts +207 -0
- package/tests/e2e/browser-public.test.ts +1 -1
- package/tests/e2e/output-formats.test.ts +10 -14
- package/tests/e2e/plugin-management.test.ts +4 -1
- package/tests/e2e/public-commands.test.ts +12 -1
- package/vitest.config.ts +1 -15
package/dist/browser/cdp.js
CHANGED
|
@@ -135,6 +135,7 @@ export class CDPBridge {
|
|
|
135
135
|
class CDPPage {
|
|
136
136
|
bridge;
|
|
137
137
|
_pageEnabled = false;
|
|
138
|
+
_lastUrl = null;
|
|
138
139
|
constructor(bridge) {
|
|
139
140
|
this.bridge = bridge;
|
|
140
141
|
}
|
|
@@ -146,6 +147,7 @@ class CDPPage {
|
|
|
146
147
|
const loadPromise = this.bridge.waitForEvent('Page.loadEventFired', 30_000).catch(() => { });
|
|
147
148
|
await this.bridge.send('Page.navigate', { url });
|
|
148
149
|
await loadPromise;
|
|
150
|
+
this._lastUrl = url;
|
|
149
151
|
if (options?.waitUntil !== 'none') {
|
|
150
152
|
const maxMs = options?.settleMs ?? 1000;
|
|
151
153
|
await this.evaluate(waitForDomStableJs(maxMs, Math.min(500, maxMs)));
|
|
@@ -251,6 +253,9 @@ class CDPPage {
|
|
|
251
253
|
async consoleMessages(_level) {
|
|
252
254
|
return [];
|
|
253
255
|
}
|
|
256
|
+
async getCurrentUrl() {
|
|
257
|
+
return this._lastUrl;
|
|
258
|
+
}
|
|
254
259
|
async installInterceptor(pattern) {
|
|
255
260
|
const { generateInterceptorJs } = await import('../interceptor.js');
|
|
256
261
|
await this.evaluate(generateInterceptorJs(JSON.stringify(pattern), {
|
package/dist/browser/discover.js
CHANGED
|
@@ -15,13 +15,17 @@ export async function checkDaemonStatus(opts) {
|
|
|
15
15
|
const port = parseInt(process.env.OPENCLI_DAEMON_PORT ?? String(DEFAULT_DAEMON_PORT), 10);
|
|
16
16
|
const controller = new AbortController();
|
|
17
17
|
const timer = setTimeout(() => controller.abort(), opts?.timeout ?? 2000);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
try {
|
|
19
|
+
const res = await fetch(`http://127.0.0.1:${port}/status`, {
|
|
20
|
+
headers: { 'X-OpenCLI': '1' },
|
|
21
|
+
signal: controller.signal,
|
|
22
|
+
});
|
|
23
|
+
const data = await res.json();
|
|
24
|
+
return { running: true, extensionConnected: data.extensionConnected, extensionVersion: data.extensionVersion };
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
clearTimeout(timer);
|
|
28
|
+
}
|
|
25
29
|
}
|
|
26
30
|
catch {
|
|
27
31
|
return { running: false, extensionConnected: false };
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export { generateSnapshotJs, scrollToRefJs, getFormStateJs } from './dom-snapsho
|
|
|
12
12
|
export { generateStealthJs } from './stealth.js';
|
|
13
13
|
export type { DomSnapshotOptions } from './dom-snapshot.js';
|
|
14
14
|
import { extractTabEntries, diffTabIndexes, appendLimited } from './tabs.js';
|
|
15
|
+
import { isRetryableSettleError } from './page.js';
|
|
15
16
|
import { withTimeoutMs } from '../runtime.js';
|
|
16
17
|
export declare const __test__: {
|
|
17
18
|
extractTabEntries: typeof extractTabEntries;
|
|
@@ -20,4 +21,5 @@ export declare const __test__: {
|
|
|
20
21
|
withTimeoutMs: typeof withTimeoutMs;
|
|
21
22
|
selectCDPTarget: (targets: import("./cdp.js").CDPTarget[]) => import("./cdp.js").CDPTarget | undefined;
|
|
22
23
|
scoreCDPTarget: (target: import("./cdp.js").CDPTarget, preferredPattern?: RegExp) => number;
|
|
24
|
+
isRetryableSettleError: typeof isRetryableSettleError;
|
|
23
25
|
};
|
package/dist/browser/index.js
CHANGED
|
@@ -12,6 +12,7 @@ export { generateSnapshotJs, scrollToRefJs, getFormStateJs } from './dom-snapsho
|
|
|
12
12
|
export { generateStealthJs } from './stealth.js';
|
|
13
13
|
import { extractTabEntries, diffTabIndexes, appendLimited } from './tabs.js';
|
|
14
14
|
import { __test__ as cdpTest } from './cdp.js';
|
|
15
|
+
import { isRetryableSettleError } from './page.js';
|
|
15
16
|
import { withTimeoutMs } from '../runtime.js';
|
|
16
17
|
export const __test__ = {
|
|
17
18
|
extractTabEntries,
|
|
@@ -20,4 +21,5 @@ export const __test__ = {
|
|
|
20
21
|
withTimeoutMs,
|
|
21
22
|
selectCDPTarget: cdpTest.selectCDPTarget,
|
|
22
23
|
scoreCDPTarget: cdpTest.scoreCDPTarget,
|
|
24
|
+
isRetryableSettleError,
|
|
23
25
|
};
|
package/dist/browser/page.d.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* chrome-extension:// tab that can't be debugged.
|
|
11
11
|
*/
|
|
12
12
|
import type { BrowserCookie, IPage, ScreenshotOptions, SnapshotOptions, WaitOptions } from '../types.js';
|
|
13
|
+
export declare function isRetryableSettleError(err: unknown): boolean;
|
|
13
14
|
/**
|
|
14
15
|
* Page — implements IPage by talking to the daemon via HTTP.
|
|
15
16
|
*/
|
|
@@ -18,6 +19,8 @@ export declare class Page implements IPage {
|
|
|
18
19
|
constructor(workspace?: string);
|
|
19
20
|
/** Active tab ID, set after navigate and used in all subsequent commands */
|
|
20
21
|
private _tabId;
|
|
22
|
+
/** Last navigated URL, tracked in-memory to avoid extra round-trips */
|
|
23
|
+
private _lastUrl;
|
|
21
24
|
/** Helper: spread workspace into command params */
|
|
22
25
|
private _wsOpt;
|
|
23
26
|
/** Helper: spread workspace + tabId into command params */
|
|
@@ -26,6 +29,7 @@ export declare class Page implements IPage {
|
|
|
26
29
|
waitUntil?: 'load' | 'none';
|
|
27
30
|
settleMs?: number;
|
|
28
31
|
}): Promise<void>;
|
|
32
|
+
getCurrentUrl(): Promise<string | null>;
|
|
29
33
|
/** Close the automation window in the extension */
|
|
30
34
|
closeWindow(): Promise<void>;
|
|
31
35
|
evaluate(js: string): Promise<unknown>;
|
package/dist/browser/page.js
CHANGED
|
@@ -16,6 +16,11 @@ import { saveBase64ToFile } from '../utils.js';
|
|
|
16
16
|
import { generateSnapshotJs, scrollToRefJs, getFormStateJs } from './dom-snapshot.js';
|
|
17
17
|
import { generateStealthJs } from './stealth.js';
|
|
18
18
|
import { clickJs, typeTextJs, pressKeyJs, waitForTextJs, scrollJs, autoScrollJs, networkRequestsJs, waitForDomStableJs, } from './dom-helpers.js';
|
|
19
|
+
export function isRetryableSettleError(err) {
|
|
20
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
21
|
+
return message.includes('Inspected target navigated or closed')
|
|
22
|
+
|| (message.includes('-32000') && message.toLowerCase().includes('target'));
|
|
23
|
+
}
|
|
19
24
|
/**
|
|
20
25
|
* Page — implements IPage by talking to the daemon via HTTP.
|
|
21
26
|
*/
|
|
@@ -26,6 +31,8 @@ export class Page {
|
|
|
26
31
|
}
|
|
27
32
|
/** Active tab ID, set after navigate and used in all subsequent commands */
|
|
28
33
|
_tabId;
|
|
34
|
+
/** Last navigated URL, tracked in-memory to avoid extra round-trips */
|
|
35
|
+
_lastUrl = null;
|
|
29
36
|
/** Helper: spread workspace into command params */
|
|
30
37
|
_wsOpt() {
|
|
31
38
|
return { workspace: this.workspace };
|
|
@@ -42,10 +49,11 @@ export class Page {
|
|
|
42
49
|
url,
|
|
43
50
|
...this._cmdOpts(),
|
|
44
51
|
});
|
|
45
|
-
// Remember the tabId for subsequent
|
|
52
|
+
// Remember the tabId and URL for subsequent calls
|
|
46
53
|
if (result?.tabId) {
|
|
47
54
|
this._tabId = result.tabId;
|
|
48
55
|
}
|
|
56
|
+
this._lastUrl = url;
|
|
49
57
|
// Inject stealth anti-detection patches (guard flag prevents double-injection).
|
|
50
58
|
try {
|
|
51
59
|
await sendCommand('exec', {
|
|
@@ -60,12 +68,36 @@ export class Page {
|
|
|
60
68
|
// settleMs is now a timeout cap (default 1000ms), not a fixed wait.
|
|
61
69
|
if (options?.waitUntil !== 'none') {
|
|
62
70
|
const maxMs = options?.settleMs ?? 1000;
|
|
63
|
-
|
|
71
|
+
const settleOpts = {
|
|
64
72
|
code: waitForDomStableJs(maxMs, Math.min(500, maxMs)),
|
|
65
73
|
...this._cmdOpts(),
|
|
66
|
-
}
|
|
74
|
+
};
|
|
75
|
+
try {
|
|
76
|
+
await sendCommand('exec', settleOpts);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
if (!isRetryableSettleError(err))
|
|
80
|
+
throw err;
|
|
81
|
+
// SPA client-side redirects can invalidate the CDP target after
|
|
82
|
+
// chrome.tabs reports 'complete'. Wait briefly for the new document
|
|
83
|
+
// to load, then retry the settle probe once.
|
|
84
|
+
try {
|
|
85
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
86
|
+
await sendCommand('exec', settleOpts);
|
|
87
|
+
}
|
|
88
|
+
catch (retryErr) {
|
|
89
|
+
if (!isRetryableSettleError(retryErr))
|
|
90
|
+
throw retryErr;
|
|
91
|
+
// Retry also failed — give up silently. Settle is best-effort
|
|
92
|
+
// after successful navigation; the next real command will surface
|
|
93
|
+
// any persistent target error immediately.
|
|
94
|
+
}
|
|
95
|
+
}
|
|
67
96
|
}
|
|
68
97
|
}
|
|
98
|
+
async getCurrentUrl() {
|
|
99
|
+
return this._lastUrl;
|
|
100
|
+
}
|
|
69
101
|
/** Close the automation window in the extension */
|
|
70
102
|
async closeWindow() {
|
|
71
103
|
try {
|
|
@@ -163,6 +195,23 @@ export class Page {
|
|
|
163
195
|
}
|
|
164
196
|
async wait(options) {
|
|
165
197
|
if (typeof options === 'number') {
|
|
198
|
+
if (options >= 1) {
|
|
199
|
+
// For waits >= 1s, use DOM-stable check: return early when the page
|
|
200
|
+
// stops mutating, with the original wait time as the hard cap.
|
|
201
|
+
// This turns e.g. `page.wait(5)` from a fixed 5s sleep into
|
|
202
|
+
// "wait until DOM is stable, max 5s" — often completing in <1s.
|
|
203
|
+
try {
|
|
204
|
+
const maxMs = options * 1000;
|
|
205
|
+
await sendCommand('exec', {
|
|
206
|
+
code: waitForDomStableJs(maxMs, Math.min(500, maxMs)),
|
|
207
|
+
...this._cmdOpts(),
|
|
208
|
+
});
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
// Fallback: fixed sleep (e.g. if page has no DOM yet)
|
|
213
|
+
}
|
|
214
|
+
}
|
|
166
215
|
await new Promise(resolve => setTimeout(resolve, options * 1000));
|
|
167
216
|
return;
|
|
168
217
|
}
|
package/dist/browser.test.js
CHANGED
|
@@ -31,6 +31,11 @@ describe('browser helpers', () => {
|
|
|
31
31
|
it('times out slow promises', async () => {
|
|
32
32
|
await expect(__test__.withTimeoutMs(new Promise(() => { }), 10, 'timeout')).rejects.toThrow('timeout');
|
|
33
33
|
});
|
|
34
|
+
it('retries settle only for target-invalidated errors', () => {
|
|
35
|
+
expect(__test__.isRetryableSettleError(new Error('{"code":-32000,"message":"Inspected target navigated or closed"}'))).toBe(true);
|
|
36
|
+
expect(__test__.isRetryableSettleError(new Error('attach failed: target no longer exists'))).toBe(false);
|
|
37
|
+
expect(__test__.isRetryableSettleError(new Error('malformed exec payload'))).toBe(false);
|
|
38
|
+
});
|
|
34
39
|
it('prefers the real Electron app target over DevTools and blank pages', () => {
|
|
35
40
|
const target = __test__.selectCDPTarget([
|
|
36
41
|
{
|
package/dist/cli-manifest.json
CHANGED
|
@@ -1311,6 +1311,464 @@
|
|
|
1311
1311
|
"mediaLinks"
|
|
1312
1312
|
]
|
|
1313
1313
|
},
|
|
1314
|
+
{
|
|
1315
|
+
"site": "bluesky",
|
|
1316
|
+
"name": "feeds",
|
|
1317
|
+
"description": "Popular Bluesky feed generators",
|
|
1318
|
+
"domain": "public.api.bsky.app",
|
|
1319
|
+
"strategy": "public",
|
|
1320
|
+
"browser": false,
|
|
1321
|
+
"args": [
|
|
1322
|
+
{
|
|
1323
|
+
"name": "limit",
|
|
1324
|
+
"type": "int",
|
|
1325
|
+
"default": 20,
|
|
1326
|
+
"required": false,
|
|
1327
|
+
"positional": false,
|
|
1328
|
+
"help": "Number of feeds"
|
|
1329
|
+
}
|
|
1330
|
+
],
|
|
1331
|
+
"columns": [
|
|
1332
|
+
"rank",
|
|
1333
|
+
"name",
|
|
1334
|
+
"likes",
|
|
1335
|
+
"creator",
|
|
1336
|
+
"description"
|
|
1337
|
+
],
|
|
1338
|
+
"pipeline": [
|
|
1339
|
+
{
|
|
1340
|
+
"fetch": {
|
|
1341
|
+
"url": "https://public.api.bsky.app/xrpc/app.bsky.unspecced.getPopularFeedGenerators?limit=${{ args.limit }}"
|
|
1342
|
+
}
|
|
1343
|
+
},
|
|
1344
|
+
{
|
|
1345
|
+
"select": "feeds"
|
|
1346
|
+
},
|
|
1347
|
+
{
|
|
1348
|
+
"map": {
|
|
1349
|
+
"rank": "${{ index + 1 }}",
|
|
1350
|
+
"name": "${{ item.displayName }}",
|
|
1351
|
+
"likes": "${{ item.likeCount }}",
|
|
1352
|
+
"creator": "${{ item.creator.handle }}",
|
|
1353
|
+
"description": "${{ item.description }}"
|
|
1354
|
+
}
|
|
1355
|
+
},
|
|
1356
|
+
{
|
|
1357
|
+
"limit": "${{ args.limit }}"
|
|
1358
|
+
}
|
|
1359
|
+
],
|
|
1360
|
+
"type": "yaml"
|
|
1361
|
+
},
|
|
1362
|
+
{
|
|
1363
|
+
"site": "bluesky",
|
|
1364
|
+
"name": "followers",
|
|
1365
|
+
"description": "List followers of a Bluesky user",
|
|
1366
|
+
"domain": "public.api.bsky.app",
|
|
1367
|
+
"strategy": "public",
|
|
1368
|
+
"browser": false,
|
|
1369
|
+
"args": [
|
|
1370
|
+
{
|
|
1371
|
+
"name": "handle",
|
|
1372
|
+
"type": "str",
|
|
1373
|
+
"required": true,
|
|
1374
|
+
"positional": true,
|
|
1375
|
+
"help": "Bluesky handle"
|
|
1376
|
+
},
|
|
1377
|
+
{
|
|
1378
|
+
"name": "limit",
|
|
1379
|
+
"type": "int",
|
|
1380
|
+
"default": 20,
|
|
1381
|
+
"required": false,
|
|
1382
|
+
"positional": false,
|
|
1383
|
+
"help": "Number of followers"
|
|
1384
|
+
}
|
|
1385
|
+
],
|
|
1386
|
+
"columns": [
|
|
1387
|
+
"rank",
|
|
1388
|
+
"handle",
|
|
1389
|
+
"name",
|
|
1390
|
+
"description"
|
|
1391
|
+
],
|
|
1392
|
+
"pipeline": [
|
|
1393
|
+
{
|
|
1394
|
+
"fetch": {
|
|
1395
|
+
"url": "https://public.api.bsky.app/xrpc/app.bsky.graph.getFollowers?actor=${{ args.handle }}&limit=${{ args.limit }}"
|
|
1396
|
+
}
|
|
1397
|
+
},
|
|
1398
|
+
{
|
|
1399
|
+
"select": "followers"
|
|
1400
|
+
},
|
|
1401
|
+
{
|
|
1402
|
+
"map": {
|
|
1403
|
+
"rank": "${{ index + 1 }}",
|
|
1404
|
+
"handle": "${{ item.handle }}",
|
|
1405
|
+
"name": "${{ item.displayName }}",
|
|
1406
|
+
"description": "${{ item.description }}"
|
|
1407
|
+
}
|
|
1408
|
+
},
|
|
1409
|
+
{
|
|
1410
|
+
"limit": "${{ args.limit }}"
|
|
1411
|
+
}
|
|
1412
|
+
],
|
|
1413
|
+
"type": "yaml"
|
|
1414
|
+
},
|
|
1415
|
+
{
|
|
1416
|
+
"site": "bluesky",
|
|
1417
|
+
"name": "following",
|
|
1418
|
+
"description": "List accounts a Bluesky user is following",
|
|
1419
|
+
"domain": "public.api.bsky.app",
|
|
1420
|
+
"strategy": "public",
|
|
1421
|
+
"browser": false,
|
|
1422
|
+
"args": [
|
|
1423
|
+
{
|
|
1424
|
+
"name": "handle",
|
|
1425
|
+
"type": "str",
|
|
1426
|
+
"required": true,
|
|
1427
|
+
"positional": true,
|
|
1428
|
+
"help": "Bluesky handle"
|
|
1429
|
+
},
|
|
1430
|
+
{
|
|
1431
|
+
"name": "limit",
|
|
1432
|
+
"type": "int",
|
|
1433
|
+
"default": 20,
|
|
1434
|
+
"required": false,
|
|
1435
|
+
"positional": false,
|
|
1436
|
+
"help": "Number of accounts"
|
|
1437
|
+
}
|
|
1438
|
+
],
|
|
1439
|
+
"columns": [
|
|
1440
|
+
"rank",
|
|
1441
|
+
"handle",
|
|
1442
|
+
"name",
|
|
1443
|
+
"description"
|
|
1444
|
+
],
|
|
1445
|
+
"pipeline": [
|
|
1446
|
+
{
|
|
1447
|
+
"fetch": {
|
|
1448
|
+
"url": "https://public.api.bsky.app/xrpc/app.bsky.graph.getFollows?actor=${{ args.handle }}&limit=${{ args.limit }}"
|
|
1449
|
+
}
|
|
1450
|
+
},
|
|
1451
|
+
{
|
|
1452
|
+
"select": "follows"
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
"map": {
|
|
1456
|
+
"rank": "${{ index + 1 }}",
|
|
1457
|
+
"handle": "${{ item.handle }}",
|
|
1458
|
+
"name": "${{ item.displayName }}",
|
|
1459
|
+
"description": "${{ item.description }}"
|
|
1460
|
+
}
|
|
1461
|
+
},
|
|
1462
|
+
{
|
|
1463
|
+
"limit": "${{ args.limit }}"
|
|
1464
|
+
}
|
|
1465
|
+
],
|
|
1466
|
+
"type": "yaml"
|
|
1467
|
+
},
|
|
1468
|
+
{
|
|
1469
|
+
"site": "bluesky",
|
|
1470
|
+
"name": "profile",
|
|
1471
|
+
"description": "Get Bluesky user profile info",
|
|
1472
|
+
"domain": "public.api.bsky.app",
|
|
1473
|
+
"strategy": "public",
|
|
1474
|
+
"browser": false,
|
|
1475
|
+
"args": [
|
|
1476
|
+
{
|
|
1477
|
+
"name": "handle",
|
|
1478
|
+
"type": "str",
|
|
1479
|
+
"required": true,
|
|
1480
|
+
"positional": true,
|
|
1481
|
+
"help": "Bluesky handle (e.g. bsky.app, jay.bsky.team)"
|
|
1482
|
+
}
|
|
1483
|
+
],
|
|
1484
|
+
"columns": [
|
|
1485
|
+
"handle",
|
|
1486
|
+
"name",
|
|
1487
|
+
"followers",
|
|
1488
|
+
"following",
|
|
1489
|
+
"posts",
|
|
1490
|
+
"description"
|
|
1491
|
+
],
|
|
1492
|
+
"pipeline": [
|
|
1493
|
+
{
|
|
1494
|
+
"fetch": {
|
|
1495
|
+
"url": "https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${{ args.handle }}"
|
|
1496
|
+
}
|
|
1497
|
+
},
|
|
1498
|
+
{
|
|
1499
|
+
"map": {
|
|
1500
|
+
"handle": "${{ item.handle }}",
|
|
1501
|
+
"name": "${{ item.displayName }}",
|
|
1502
|
+
"followers": "${{ item.followersCount }}",
|
|
1503
|
+
"following": "${{ item.followsCount }}",
|
|
1504
|
+
"posts": "${{ item.postsCount }}",
|
|
1505
|
+
"description": "${{ item.description }}"
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
],
|
|
1509
|
+
"type": "yaml"
|
|
1510
|
+
},
|
|
1511
|
+
{
|
|
1512
|
+
"site": "bluesky",
|
|
1513
|
+
"name": "search",
|
|
1514
|
+
"description": "Search Bluesky users",
|
|
1515
|
+
"domain": "public.api.bsky.app",
|
|
1516
|
+
"strategy": "public",
|
|
1517
|
+
"browser": false,
|
|
1518
|
+
"args": [
|
|
1519
|
+
{
|
|
1520
|
+
"name": "query",
|
|
1521
|
+
"type": "str",
|
|
1522
|
+
"required": true,
|
|
1523
|
+
"positional": true,
|
|
1524
|
+
"help": "Search query"
|
|
1525
|
+
},
|
|
1526
|
+
{
|
|
1527
|
+
"name": "limit",
|
|
1528
|
+
"type": "int",
|
|
1529
|
+
"default": 10,
|
|
1530
|
+
"required": false,
|
|
1531
|
+
"positional": false,
|
|
1532
|
+
"help": "Number of results"
|
|
1533
|
+
}
|
|
1534
|
+
],
|
|
1535
|
+
"columns": [
|
|
1536
|
+
"rank",
|
|
1537
|
+
"handle",
|
|
1538
|
+
"name",
|
|
1539
|
+
"followers",
|
|
1540
|
+
"description"
|
|
1541
|
+
],
|
|
1542
|
+
"pipeline": [
|
|
1543
|
+
{
|
|
1544
|
+
"fetch": {
|
|
1545
|
+
"url": "https://public.api.bsky.app/xrpc/app.bsky.actor.searchActors?q=${{ args.query }}&limit=${{ args.limit }}"
|
|
1546
|
+
}
|
|
1547
|
+
},
|
|
1548
|
+
{
|
|
1549
|
+
"select": "actors"
|
|
1550
|
+
},
|
|
1551
|
+
{
|
|
1552
|
+
"map": {
|
|
1553
|
+
"rank": "${{ index + 1 }}",
|
|
1554
|
+
"handle": "${{ item.handle }}",
|
|
1555
|
+
"name": "${{ item.displayName }}",
|
|
1556
|
+
"followers": "${{ item.followersCount }}",
|
|
1557
|
+
"description": "${{ item.description }}"
|
|
1558
|
+
}
|
|
1559
|
+
},
|
|
1560
|
+
{
|
|
1561
|
+
"limit": "${{ args.limit }}"
|
|
1562
|
+
}
|
|
1563
|
+
],
|
|
1564
|
+
"type": "yaml"
|
|
1565
|
+
},
|
|
1566
|
+
{
|
|
1567
|
+
"site": "bluesky",
|
|
1568
|
+
"name": "starter-packs",
|
|
1569
|
+
"description": "Get starter packs created by a Bluesky user",
|
|
1570
|
+
"domain": "public.api.bsky.app",
|
|
1571
|
+
"strategy": "public",
|
|
1572
|
+
"browser": false,
|
|
1573
|
+
"args": [
|
|
1574
|
+
{
|
|
1575
|
+
"name": "handle",
|
|
1576
|
+
"type": "str",
|
|
1577
|
+
"required": true,
|
|
1578
|
+
"positional": true,
|
|
1579
|
+
"help": "Bluesky handle"
|
|
1580
|
+
},
|
|
1581
|
+
{
|
|
1582
|
+
"name": "limit",
|
|
1583
|
+
"type": "int",
|
|
1584
|
+
"default": 10,
|
|
1585
|
+
"required": false,
|
|
1586
|
+
"positional": false,
|
|
1587
|
+
"help": "Number of starter packs"
|
|
1588
|
+
}
|
|
1589
|
+
],
|
|
1590
|
+
"columns": [
|
|
1591
|
+
"rank",
|
|
1592
|
+
"name",
|
|
1593
|
+
"description",
|
|
1594
|
+
"members",
|
|
1595
|
+
"joins"
|
|
1596
|
+
],
|
|
1597
|
+
"pipeline": [
|
|
1598
|
+
{
|
|
1599
|
+
"fetch": {
|
|
1600
|
+
"url": "https://public.api.bsky.app/xrpc/app.bsky.graph.getActorStarterPacks?actor=${{ args.handle }}&limit=${{ args.limit }}"
|
|
1601
|
+
}
|
|
1602
|
+
},
|
|
1603
|
+
{
|
|
1604
|
+
"select": "starterPacks"
|
|
1605
|
+
},
|
|
1606
|
+
{
|
|
1607
|
+
"map": {
|
|
1608
|
+
"rank": "${{ index + 1 }}",
|
|
1609
|
+
"name": "${{ item.record.name }}",
|
|
1610
|
+
"description": "${{ item.record.description }}",
|
|
1611
|
+
"members": "${{ item.listItemCount }}",
|
|
1612
|
+
"joins": "${{ item.joinedAllTimeCount }}"
|
|
1613
|
+
}
|
|
1614
|
+
},
|
|
1615
|
+
{
|
|
1616
|
+
"limit": "${{ args.limit }}"
|
|
1617
|
+
}
|
|
1618
|
+
],
|
|
1619
|
+
"type": "yaml"
|
|
1620
|
+
},
|
|
1621
|
+
{
|
|
1622
|
+
"site": "bluesky",
|
|
1623
|
+
"name": "thread",
|
|
1624
|
+
"description": "Get a Bluesky post thread with replies",
|
|
1625
|
+
"domain": "public.api.bsky.app",
|
|
1626
|
+
"strategy": "public",
|
|
1627
|
+
"browser": false,
|
|
1628
|
+
"args": [
|
|
1629
|
+
{
|
|
1630
|
+
"name": "uri",
|
|
1631
|
+
"type": "str",
|
|
1632
|
+
"required": true,
|
|
1633
|
+
"positional": true,
|
|
1634
|
+
"help": "Post AT URI (at://did:.../app.bsky.feed.post/...) or bsky.app URL"
|
|
1635
|
+
},
|
|
1636
|
+
{
|
|
1637
|
+
"name": "limit",
|
|
1638
|
+
"type": "int",
|
|
1639
|
+
"default": 20,
|
|
1640
|
+
"required": false,
|
|
1641
|
+
"positional": false,
|
|
1642
|
+
"help": "Number of replies"
|
|
1643
|
+
}
|
|
1644
|
+
],
|
|
1645
|
+
"columns": [
|
|
1646
|
+
"author",
|
|
1647
|
+
"text",
|
|
1648
|
+
"likes",
|
|
1649
|
+
"reposts",
|
|
1650
|
+
"replies_count"
|
|
1651
|
+
],
|
|
1652
|
+
"pipeline": [
|
|
1653
|
+
{
|
|
1654
|
+
"fetch": {
|
|
1655
|
+
"url": "https://public.api.bsky.app/xrpc/app.bsky.feed.getPostThread?uri=${{ args.uri }}&depth=2"
|
|
1656
|
+
}
|
|
1657
|
+
},
|
|
1658
|
+
{
|
|
1659
|
+
"select": "thread"
|
|
1660
|
+
},
|
|
1661
|
+
{
|
|
1662
|
+
"map": {
|
|
1663
|
+
"author": "${{ item.post.author.handle }}",
|
|
1664
|
+
"text": "${{ item.post.record.text }}",
|
|
1665
|
+
"likes": "${{ item.post.likeCount }}",
|
|
1666
|
+
"reposts": "${{ item.post.repostCount }}",
|
|
1667
|
+
"replies_count": "${{ item.post.replyCount }}"
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
],
|
|
1671
|
+
"type": "yaml"
|
|
1672
|
+
},
|
|
1673
|
+
{
|
|
1674
|
+
"site": "bluesky",
|
|
1675
|
+
"name": "trending",
|
|
1676
|
+
"description": "Trending topics on Bluesky",
|
|
1677
|
+
"domain": "public.api.bsky.app",
|
|
1678
|
+
"strategy": "public",
|
|
1679
|
+
"browser": false,
|
|
1680
|
+
"args": [
|
|
1681
|
+
{
|
|
1682
|
+
"name": "limit",
|
|
1683
|
+
"type": "int",
|
|
1684
|
+
"default": 20,
|
|
1685
|
+
"required": false,
|
|
1686
|
+
"positional": false,
|
|
1687
|
+
"help": "Number of topics"
|
|
1688
|
+
}
|
|
1689
|
+
],
|
|
1690
|
+
"columns": [
|
|
1691
|
+
"rank",
|
|
1692
|
+
"topic",
|
|
1693
|
+
"link"
|
|
1694
|
+
],
|
|
1695
|
+
"pipeline": [
|
|
1696
|
+
{
|
|
1697
|
+
"fetch": {
|
|
1698
|
+
"url": "https://public.api.bsky.app/xrpc/app.bsky.unspecced.getTrendingTopics"
|
|
1699
|
+
}
|
|
1700
|
+
},
|
|
1701
|
+
{
|
|
1702
|
+
"select": "topics"
|
|
1703
|
+
},
|
|
1704
|
+
{
|
|
1705
|
+
"map": {
|
|
1706
|
+
"rank": "${{ index + 1 }}",
|
|
1707
|
+
"topic": "${{ item.topic }}",
|
|
1708
|
+
"link": "${{ item.link }}"
|
|
1709
|
+
}
|
|
1710
|
+
},
|
|
1711
|
+
{
|
|
1712
|
+
"limit": "${{ args.limit }}"
|
|
1713
|
+
}
|
|
1714
|
+
],
|
|
1715
|
+
"type": "yaml"
|
|
1716
|
+
},
|
|
1717
|
+
{
|
|
1718
|
+
"site": "bluesky",
|
|
1719
|
+
"name": "user",
|
|
1720
|
+
"description": "Get recent posts from a Bluesky user",
|
|
1721
|
+
"domain": "public.api.bsky.app",
|
|
1722
|
+
"strategy": "public",
|
|
1723
|
+
"browser": false,
|
|
1724
|
+
"args": [
|
|
1725
|
+
{
|
|
1726
|
+
"name": "handle",
|
|
1727
|
+
"type": "str",
|
|
1728
|
+
"required": true,
|
|
1729
|
+
"positional": true,
|
|
1730
|
+
"help": "Bluesky handle (e.g. bsky.app)"
|
|
1731
|
+
},
|
|
1732
|
+
{
|
|
1733
|
+
"name": "limit",
|
|
1734
|
+
"type": "int",
|
|
1735
|
+
"default": 20,
|
|
1736
|
+
"required": false,
|
|
1737
|
+
"positional": false,
|
|
1738
|
+
"help": "Number of posts"
|
|
1739
|
+
}
|
|
1740
|
+
],
|
|
1741
|
+
"columns": [
|
|
1742
|
+
"rank",
|
|
1743
|
+
"text",
|
|
1744
|
+
"likes",
|
|
1745
|
+
"reposts",
|
|
1746
|
+
"replies"
|
|
1747
|
+
],
|
|
1748
|
+
"pipeline": [
|
|
1749
|
+
{
|
|
1750
|
+
"fetch": {
|
|
1751
|
+
"url": "https://public.api.bsky.app/xrpc/app.bsky.feed.getAuthorFeed?actor=${{ args.handle }}&limit=${{ args.limit }}"
|
|
1752
|
+
}
|
|
1753
|
+
},
|
|
1754
|
+
{
|
|
1755
|
+
"select": "feed"
|
|
1756
|
+
},
|
|
1757
|
+
{
|
|
1758
|
+
"map": {
|
|
1759
|
+
"rank": "${{ index + 1 }}",
|
|
1760
|
+
"text": "${{ item.post.record.text }}",
|
|
1761
|
+
"likes": "${{ item.post.likeCount }}",
|
|
1762
|
+
"reposts": "${{ item.post.repostCount }}",
|
|
1763
|
+
"replies": "${{ item.post.replyCount }}"
|
|
1764
|
+
}
|
|
1765
|
+
},
|
|
1766
|
+
{
|
|
1767
|
+
"limit": "${{ args.limit }}"
|
|
1768
|
+
}
|
|
1769
|
+
],
|
|
1770
|
+
"type": "yaml"
|
|
1771
|
+
},
|
|
1314
1772
|
{
|
|
1315
1773
|
"site": "boss",
|
|
1316
1774
|
"name": "batchgreet",
|
|
@@ -11801,7 +12259,7 @@
|
|
|
11801
12259
|
{
|
|
11802
12260
|
"name": "images",
|
|
11803
12261
|
"type": "str",
|
|
11804
|
-
"required":
|
|
12262
|
+
"required": true,
|
|
11805
12263
|
"help": "图片路径,逗号分隔,最多9张 (jpg/png/gif/webp)"
|
|
11806
12264
|
},
|
|
11807
12265
|
{
|
|
@@ -11856,6 +12314,7 @@
|
|
|
11856
12314
|
"title",
|
|
11857
12315
|
"author",
|
|
11858
12316
|
"likes",
|
|
12317
|
+
"published_at",
|
|
11859
12318
|
"url"
|
|
11860
12319
|
]
|
|
11861
12320
|
},
|