@nocoo/zhe 1.19.3 → 1.24.1
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/README.md +31 -0
- package/dist/api/client.d.ts +12 -2
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +32 -11
- package/dist/api/client.js.map +1 -1
- package/dist/api/types.d.ts.map +1 -1
- package/dist/commands/connector.d.ts +2 -0
- package/dist/commands/connector.d.ts.map +1 -0
- package/dist/commands/connector.js +103 -0
- package/dist/commands/connector.js.map +1 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +1 -1
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/delete.js +1 -1
- package/dist/commands/delete.js.map +1 -1
- package/dist/commands/folder.d.ts.map +1 -1
- package/dist/commands/folder.js +1 -1
- package/dist/commands/folder.js.map +1 -1
- package/dist/commands/folders.js +1 -1
- package/dist/commands/folders.js.map +1 -1
- package/dist/commands/get.js +1 -1
- package/dist/commands/get.js.map +1 -1
- package/dist/commands/idea/add.d.ts.map +1 -1
- package/dist/commands/idea/add.js +1 -1
- package/dist/commands/idea/add.js.map +1 -1
- package/dist/commands/idea/delete.js +1 -1
- package/dist/commands/idea/delete.js.map +1 -1
- package/dist/commands/idea/get.d.ts.map +1 -1
- package/dist/commands/idea/get.js +2 -2
- package/dist/commands/idea/get.js.map +1 -1
- package/dist/commands/idea/helpers.d.ts.map +1 -1
- package/dist/commands/idea/helpers.js +1 -1
- package/dist/commands/idea/helpers.js.map +1 -1
- package/dist/commands/idea/list.d.ts.map +1 -1
- package/dist/commands/idea/list.js +2 -2
- package/dist/commands/idea/list.js.map +1 -1
- package/dist/commands/idea/update.d.ts.map +1 -1
- package/dist/commands/idea/update.js +1 -1
- package/dist/commands/idea/update.js.map +1 -1
- package/dist/commands/idea.js +1 -1
- package/dist/commands/idea.js.map +1 -1
- package/dist/commands/inbox.js +1 -1
- package/dist/commands/inbox.js.map +1 -1
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +3 -4
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +3 -3
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.js +1 -1
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/open.js +1 -1
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/tag.d.ts.map +1 -1
- package/dist/commands/tag.js +1 -1
- package/dist/commands/tag.js.map +1 -1
- package/dist/commands/tags.js +1 -1
- package/dist/commands/tags.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +1 -1
- package/dist/commands/update.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/connector/core.d.ts +64 -0
- package/dist/connector/core.d.ts.map +1 -0
- package/dist/connector/core.js +237 -0
- package/dist/connector/core.js.map +1 -0
- package/dist/connector/dns.d.ts +3 -0
- package/dist/connector/dns.d.ts.map +1 -0
- package/dist/connector/dns.js +92 -0
- package/dist/connector/dns.js.map +1 -0
- package/dist/connector/download.d.ts +5 -0
- package/dist/connector/download.d.ts.map +1 -0
- package/dist/connector/download.js +190 -0
- package/dist/connector/download.js.map +1 -0
- package/dist/connector/log.d.ts +24 -0
- package/dist/connector/log.d.ts.map +1 -0
- package/dist/connector/log.js +145 -0
- package/dist/connector/log.js.map +1 -0
- package/dist/connector/opencli.d.ts +6 -0
- package/dist/connector/opencli.d.ts.map +1 -0
- package/dist/connector/opencli.js +136 -0
- package/dist/connector/opencli.js.map +1 -0
- package/dist/connector/runtime.d.ts +13 -0
- package/dist/connector/runtime.d.ts.map +1 -0
- package/dist/connector/runtime.js +179 -0
- package/dist/connector/runtime.js.map +1 -0
- package/dist/connector/types.d.ts +42 -0
- package/dist/connector/types.d.ts.map +1 -0
- package/dist/connector/types.js +2 -0
- package/dist/connector/types.js.map +1 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/resolve.d.ts.map +1 -1
- package/dist/utils/resolve.js +1 -1
- package/dist/utils/resolve.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +13 -7
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PollResult } from "./runtime.js";
|
|
2
|
+
import type { ConnectorProgress, ConnectorStatus } from "./types.js";
|
|
3
|
+
/** Only known codes become log text; upstream errors may contain cookies or response bodies. */
|
|
4
|
+
export declare function connectorErrorHint(error: unknown): string;
|
|
5
|
+
export declare class ConnectorLogger {
|
|
6
|
+
private json;
|
|
7
|
+
private started;
|
|
8
|
+
private lastProgress;
|
|
9
|
+
private active?;
|
|
10
|
+
private queueSnapshot;
|
|
11
|
+
private totalMedia;
|
|
12
|
+
private stats;
|
|
13
|
+
constructor(json?: boolean);
|
|
14
|
+
private write;
|
|
15
|
+
start(): void;
|
|
16
|
+
queue(status: ConnectorStatus): void;
|
|
17
|
+
progress: (event: ConnectorProgress) => void;
|
|
18
|
+
tick(): void;
|
|
19
|
+
result(result: PollResult, durationMs: number, watching?: boolean): void;
|
|
20
|
+
offline(error: unknown): void;
|
|
21
|
+
private summary;
|
|
22
|
+
stop(): void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=log.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/connector/log.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA0BrE,gGAAgG;AAChG,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAUzD;AAED,qBAAa,eAAe;IAiBd,OAAO,CAAC,IAAI;IAhBxB,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,MAAM,CAAC,CAAoB;IACnC,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,KAAK,CASX;IAEF,YAAoB,IAAI,UAAQ,EAAI;IAEpC,OAAO,CAAC,KAAK;IAkBb,KAAK,SAKJ;IAED,KAAK,CAAC,MAAM,EAAE,eAAe,QAU5B;IAED,QAAQ,UAAW,iBAAiB,UAclC;IAEF,IAAI,SAMH;IAED,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,UAAQ,QAkB9D;IAED,OAAO,CAAC,KAAK,EAAE,OAAO,QAOrB;IAED,OAAO,CAAC,OAAO;IAKf,IAAI,SAMH;CACF"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { formatDuration, formatSize, pc } from "@nocoo/base-cli";
|
|
2
|
+
import { ApiClientError } from "../api/client.js";
|
|
3
|
+
import { CLI_VERSION } from "../version.js";
|
|
4
|
+
import { ConnectorError } from "./core.js";
|
|
5
|
+
const fallbackHint = "Connector processing failed. Check the connection and retry.";
|
|
6
|
+
const hints = {
|
|
7
|
+
0: "Cannot reach Zhe. Check the network connection.",
|
|
8
|
+
401: "API Key missing, invalid or revoked. Run `zhe login` with a valid key.",
|
|
9
|
+
403: "Connector permission missing or expired. Use a key with `connector:write` created within 30 days.",
|
|
10
|
+
409: "This job's lease is no longer valid; it will not be overwritten.",
|
|
11
|
+
429: "API rate limit reached. Waiting before the next poll.",
|
|
12
|
+
needs_login: "Connect the OpenCLI browser extension and sign in to X.",
|
|
13
|
+
opencli_unavailable: "OpenCLI is unavailable. Check its browser extension and connection.",
|
|
14
|
+
unsupported_opencli_version: "OpenCLI version mismatch. Reinstall the Zhe CLI dependencies.",
|
|
15
|
+
adapter_contract_changed: "OpenCLI adapter changed. Update the Zhe CLI.",
|
|
16
|
+
post_unavailable: "The saved X post is unavailable or protected.",
|
|
17
|
+
invalid_post_id: "The saved X post ID is invalid.",
|
|
18
|
+
invalid_media: "Media has an unsupported type or exceeds the size limit.",
|
|
19
|
+
decode_failed: "Media verification failed. Check FFmpeg and ffprobe are installed.",
|
|
20
|
+
download_failed: "Media download failed. The saved text is retained for retry.",
|
|
21
|
+
size_mismatch: "Media download was incomplete or its size changed.",
|
|
22
|
+
unsafe_redirect: "The media redirect could not be verified.",
|
|
23
|
+
unsafe_media_address: "The media address could not be verified.",
|
|
24
|
+
media_dns_unavailable: "Media DNS lookup failed. Check the network connection.",
|
|
25
|
+
interrupted: "Processing interrupted; unfinished work can be retried.",
|
|
26
|
+
connector_error: fallbackHint,
|
|
27
|
+
};
|
|
28
|
+
/** Only known codes become log text; upstream errors may contain cookies or response bodies. */
|
|
29
|
+
export function connectorErrorHint(error) {
|
|
30
|
+
const code = error instanceof ApiClientError
|
|
31
|
+
? error.status
|
|
32
|
+
: error instanceof ConnectorError
|
|
33
|
+
? error.code
|
|
34
|
+
: error;
|
|
35
|
+
return (typeof code === "string" || typeof code === "number") && typeof hints[code] === "string"
|
|
36
|
+
? hints[code]
|
|
37
|
+
: fallbackHint;
|
|
38
|
+
}
|
|
39
|
+
export class ConnectorLogger {
|
|
40
|
+
json;
|
|
41
|
+
started = Date.now();
|
|
42
|
+
lastProgress = Date.now();
|
|
43
|
+
active;
|
|
44
|
+
queueSnapshot = "";
|
|
45
|
+
totalMedia = 0;
|
|
46
|
+
stats = {
|
|
47
|
+
complete: 0,
|
|
48
|
+
partial: 0,
|
|
49
|
+
failed: 0,
|
|
50
|
+
interrupted: 0,
|
|
51
|
+
media: 0,
|
|
52
|
+
skipped: 0,
|
|
53
|
+
bytes: 0,
|
|
54
|
+
errors: 0,
|
|
55
|
+
};
|
|
56
|
+
constructor(json = false) {
|
|
57
|
+
this.json = json;
|
|
58
|
+
}
|
|
59
|
+
write(event, message, fields = {}) {
|
|
60
|
+
const time = new Date();
|
|
61
|
+
if (this.json) {
|
|
62
|
+
console.log(JSON.stringify({ time: time.toISOString(), event, message, ...fields }));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const color = ["failed", "offline"].includes(event)
|
|
66
|
+
? pc.red
|
|
67
|
+
: ["warning", "partial", "interrupted"].includes(event)
|
|
68
|
+
? pc.yellow
|
|
69
|
+
: ["complete", "uploaded", "saved"].includes(event)
|
|
70
|
+
? pc.green
|
|
71
|
+
: pc.cyan;
|
|
72
|
+
console.log(`${pc.dim(time.toLocaleTimeString("en-GB", { hour12: false }))} ${color(event.toUpperCase().padEnd(11))} ${message}`);
|
|
73
|
+
}
|
|
74
|
+
start() {
|
|
75
|
+
this.write("ready", `Zhe · X Connector ${CLI_VERSION} · one job at a time · 20s between polls · Ctrl+C to stop`);
|
|
76
|
+
}
|
|
77
|
+
queue(status) {
|
|
78
|
+
const states = Object.fromEntries(status.states.map(({ state, count }) => [state, count]));
|
|
79
|
+
const snapshot = JSON.stringify([states, status.expiresAt]);
|
|
80
|
+
if (snapshot === this.queueSnapshot)
|
|
81
|
+
return;
|
|
82
|
+
this.queueSnapshot = snapshot;
|
|
83
|
+
this.write("queue", `${["pending", "running", "complete", "partial", "failed", "unavailable"].map((state) => `${states[state] ?? 0} ${state}`).join(" · ")} · key expires ${new Date(status.expiresAt).toISOString().slice(0, 10)}`, { states, expiresAt: status.expiresAt });
|
|
84
|
+
}
|
|
85
|
+
progress = (event) => {
|
|
86
|
+
this.active = event;
|
|
87
|
+
this.lastProgress = Date.now();
|
|
88
|
+
if (event.stage === "claim")
|
|
89
|
+
this.totalMedia = 0;
|
|
90
|
+
if (event.stage === "capture")
|
|
91
|
+
this.totalMedia = event.total ?? 0;
|
|
92
|
+
if (event.stage === "uploaded")
|
|
93
|
+
this.stats.bytes += event.bytes ?? 0;
|
|
94
|
+
if (event.stage === "skipped")
|
|
95
|
+
this.stats.skipped++;
|
|
96
|
+
let message = event.message;
|
|
97
|
+
if (event.stage === "download" && event.bytes) {
|
|
98
|
+
const percent = Math.min(100, Math.floor(((event.received ?? 0) / event.bytes) * 100));
|
|
99
|
+
const filled = Math.floor(percent / 10);
|
|
100
|
+
message += ` [${"━".repeat(filled)}${"·".repeat(10 - filled)}] ${percent}% · ${formatSize(event.received ?? 0)} / ${formatSize(event.bytes)}`;
|
|
101
|
+
}
|
|
102
|
+
else if (event.bytes)
|
|
103
|
+
message += ` · ${formatSize(event.bytes)}`;
|
|
104
|
+
this.write(event.stage, message, { ...event, message });
|
|
105
|
+
};
|
|
106
|
+
tick() {
|
|
107
|
+
if (!this.active || Date.now() - this.lastProgress < 10_000)
|
|
108
|
+
return;
|
|
109
|
+
this.write("working", `${this.active.stage}: ${this.active.message} · still running (${formatDuration(Date.now() - this.lastProgress)} since last progress)`);
|
|
110
|
+
}
|
|
111
|
+
result(result, durationMs, watching = false) {
|
|
112
|
+
this.active = undefined;
|
|
113
|
+
const interrupted = result.error === "interrupted";
|
|
114
|
+
if (result.status !== "idle") {
|
|
115
|
+
this.stats[interrupted ? "interrupted" : result.status]++;
|
|
116
|
+
this.stats.media += result.media;
|
|
117
|
+
}
|
|
118
|
+
const detail = result.status === "idle"
|
|
119
|
+
? "No job ready"
|
|
120
|
+
: `${result.media}/${this.totalMedia} media archived · ${formatDuration(durationMs)}${result.error ? ` · ${connectorErrorHint(result.errorStatus ?? result.error)}` : ""}`;
|
|
121
|
+
this.write(interrupted ? "interrupted" : result.status, `${detail}${watching ? " · next poll in 20s" : ""}`, { ...result, durationMs, stats: { ...this.stats } });
|
|
122
|
+
if (result.status !== "idle")
|
|
123
|
+
this.write("session", this.summary(), { stats: { ...this.stats } });
|
|
124
|
+
}
|
|
125
|
+
offline(error) {
|
|
126
|
+
this.active = undefined;
|
|
127
|
+
this.stats.errors++;
|
|
128
|
+
this.write("offline", `${connectorErrorHint(error)} Next poll in 20s.`, {
|
|
129
|
+
status: "offline",
|
|
130
|
+
code: error instanceof ApiClientError ? error.status : "connector_error",
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
summary() {
|
|
134
|
+
const s = this.stats;
|
|
135
|
+
return `${s.complete} complete · ${s.partial} partial · ${s.failed} failed · ${s.interrupted} interrupted · ${s.media} media · ${s.skipped} skipped · ${formatSize(s.bytes)} uploaded · ${s.errors} connection errors · uptime ${formatDuration(Date.now() - this.started)}`;
|
|
136
|
+
}
|
|
137
|
+
stop() {
|
|
138
|
+
this.active = undefined;
|
|
139
|
+
this.write("stopped", this.summary(), {
|
|
140
|
+
stats: { ...this.stats },
|
|
141
|
+
durationMs: Date.now() - this.started,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/connector/log.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type XCapture } from "./core.js";
|
|
2
|
+
export declare function readInChild(postId: string): Promise<XCapture>;
|
|
3
|
+
/** Isolate raw browser responses and upstream logs; IPC only carries the normalized focal post. */
|
|
4
|
+
export declare function readPost(postId: string, signal?: AbortSignal): Promise<XCapture>;
|
|
5
|
+
export declare function runIsolated(postId: string): Promise<void>;
|
|
6
|
+
//# sourceMappingURL=opencli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencli.d.ts","sourceRoot":"","sources":["../../src/connector/opencli.ts"],"names":[],"mappings":"AAMA,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,WAAW,CAAC;AAgBnB,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAsEnE;AAED,mGAAmG;AACnG,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkChF;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB/D"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { fork } from "node:child_process";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { dirname, join, resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
|
+
import { ConnectorError, collectTweetEntities, normalizeXPost, record, } from "./core.js";
|
|
8
|
+
export async function readInChild(postId) {
|
|
9
|
+
const root = process.env.ZHE_OPENCLI_ROOT ??
|
|
10
|
+
resolve(dirname(createRequire(import.meta.url).resolve("@jackwener/opencli/registry")), "../..");
|
|
11
|
+
const manifest = JSON.parse(await readFile(join(root, "package.json"), "utf8"));
|
|
12
|
+
if (manifest.version !== "1.8.6")
|
|
13
|
+
throw new ConnectorError("unsupported_opencli_version");
|
|
14
|
+
const { BrowserBridge } = (await import(pathToFileURL(join(root, "dist/src/browser/bridge.js")).href));
|
|
15
|
+
const { getRegistry } = (await import(pathToFileURL(join(root, "dist/src/registry.js")).href));
|
|
16
|
+
await import(pathToFileURL(join(root, "clis/twitter/thread.js")).href);
|
|
17
|
+
const bridge = new BrowserBridge();
|
|
18
|
+
let page;
|
|
19
|
+
const entities = new Map();
|
|
20
|
+
try {
|
|
21
|
+
page = await bridge.connect({
|
|
22
|
+
session: `zhe-connector-${randomUUID()}`,
|
|
23
|
+
windowMode: "background",
|
|
24
|
+
siteSession: "ephemeral",
|
|
25
|
+
});
|
|
26
|
+
await page.goto(`https://x.com/i/status/${postId}`, { waitUntil: "none" });
|
|
27
|
+
await new Promise((r) => setTimeout(r, 1200));
|
|
28
|
+
const proxy = new Proxy(page, {
|
|
29
|
+
get(target, key) {
|
|
30
|
+
if (key === "goto")
|
|
31
|
+
return (url) => target.goto(url, { waitUntil: "none" });
|
|
32
|
+
if (key === "evaluate")
|
|
33
|
+
return async (code) => {
|
|
34
|
+
const value = await target.evaluate(code);
|
|
35
|
+
if (code.includes("TweetDetail")) {
|
|
36
|
+
for (const [id, post] of collectTweetEntities(value))
|
|
37
|
+
entities.set(id, post);
|
|
38
|
+
// Stop reply pagination: the task only concerns its saved focal post.
|
|
39
|
+
const instructions = record(record(record(value).data).threaded_conversation_with_injections_v2).instructions;
|
|
40
|
+
if (Array.isArray(instructions))
|
|
41
|
+
for (const instruction of instructions) {
|
|
42
|
+
const item = record(instruction);
|
|
43
|
+
if (Array.isArray(item.entries))
|
|
44
|
+
item.entries = item.entries.filter((e) => !String(record(e).entryId ?? "").startsWith("cursor-") &&
|
|
45
|
+
!record(record(e).content).cursorType);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
};
|
|
50
|
+
const value = Reflect.get(target, key);
|
|
51
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
const adapter = getRegistry().get("twitter/thread");
|
|
55
|
+
if (adapter?.access !== "read")
|
|
56
|
+
throw new ConnectorError("adapter_contract_changed");
|
|
57
|
+
await adapter.func(proxy, { "tweet-id": postId, limit: 1 });
|
|
58
|
+
const capture = normalizeXPost(entities.get(postId), postId);
|
|
59
|
+
if (!capture)
|
|
60
|
+
throw new ConnectorError("post_unavailable");
|
|
61
|
+
return capture;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
throw error instanceof ConnectorError ? error : new ConnectorError("needs_login");
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
await page?.closeWindow().catch(() => { });
|
|
68
|
+
await bridge.close().catch(() => { });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Isolate raw browser responses and upstream logs; IPC only carries the normalized focal post. */
|
|
72
|
+
export function readPost(postId, signal) {
|
|
73
|
+
if (!/^\d{1,22}$/.test(postId))
|
|
74
|
+
throw new ConnectorError("invalid_post_id");
|
|
75
|
+
return new Promise((resolveResult, reject) => {
|
|
76
|
+
const child = fork(fileURLToPath(import.meta.url), ["--isolated", postId], {
|
|
77
|
+
stdio: ["ignore", "ignore", "ignore", "ipc"],
|
|
78
|
+
});
|
|
79
|
+
const finish = () => {
|
|
80
|
+
clearTimeout(timer);
|
|
81
|
+
signal?.removeEventListener("abort", abort);
|
|
82
|
+
};
|
|
83
|
+
const abort = () => {
|
|
84
|
+
child.kill("SIGTERM");
|
|
85
|
+
finish();
|
|
86
|
+
reject(new ConnectorError("interrupted"));
|
|
87
|
+
};
|
|
88
|
+
const timer = setTimeout(abort, 120_000);
|
|
89
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
90
|
+
child.once("message", (message) => {
|
|
91
|
+
finish();
|
|
92
|
+
const value = record(message);
|
|
93
|
+
if (value.ok === true)
|
|
94
|
+
resolveResult(value.capture);
|
|
95
|
+
else
|
|
96
|
+
reject(new ConnectorError(typeof value.code === "string" ? value.code : "connector_error"));
|
|
97
|
+
});
|
|
98
|
+
child.once("error", () => {
|
|
99
|
+
finish();
|
|
100
|
+
reject(new ConnectorError("opencli_unavailable"));
|
|
101
|
+
});
|
|
102
|
+
child.once("close", () => {
|
|
103
|
+
finish();
|
|
104
|
+
reject(new ConnectorError("opencli_unavailable"));
|
|
105
|
+
});
|
|
106
|
+
if (signal?.aborted)
|
|
107
|
+
abort();
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
export async function runIsolated(postId) {
|
|
111
|
+
let result;
|
|
112
|
+
try {
|
|
113
|
+
result = { ok: true, capture: await readInChild(postId) };
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
result = {
|
|
117
|
+
ok: false,
|
|
118
|
+
code: error instanceof ConnectorError ? error.code : "opencli_unavailable",
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
await new Promise((done, reject) => {
|
|
123
|
+
if (!process.send)
|
|
124
|
+
return reject(new ConnectorError("opencli_unavailable"));
|
|
125
|
+
process.send(result, (error) => (error ? reject(error) : done()));
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
process.disconnect?.();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (process.argv[2] === "--isolated" &&
|
|
133
|
+
process.argv[1] &&
|
|
134
|
+
resolve(process.argv[1]) === fileURLToPath(import.meta.url))
|
|
135
|
+
await runIsolated(process.argv[3] ?? "");
|
|
136
|
+
//# sourceMappingURL=opencli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencli.js","sourceRoot":"","sources":["../../src/connector/opencli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,MAAM,GAEP,MAAM,WAAW,CAAC;AAgBnB,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAc;IAC9C,MAAM,IAAI,GACR,OAAO,CAAC,GAAG,CAAC,gBAAgB;QAC5B,OAAO,CACL,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC,EAC9E,OAAO,CACR,CAAC;IACJ,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAE7E,CAAC;IACF,IAAI,QAAQ,CAAC,OAAO,KAAK,OAAO;QAAE,MAAM,IAAI,cAAc,CAAC,6BAA6B,CAAC,CAAC;IAC1F,MAAM,EAAE,aAAa,EAAE,GAAG,CAAC,MAAM,MAAM,CACrC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAC7D,CAAwC,CAAC;IAC1C,MAAM,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,MAAM,CACnC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC,CAAC,IAAI,CACvD,CAAgD,CAAC;IAClD,MAAM,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;IACnC,IAAI,IAAsB,CAAC;IAC3B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAmB,CAAC;IAC5C,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;YAC1B,OAAO,EAAE,iBAAiB,UAAU,EAAE,EAAE;YACxC,UAAU,EAAE,YAAY;YACxB,WAAW,EAAE,WAAW;SACzB,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,IAAI,CAAC,0BAA0B,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3E,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE;YAC5B,GAAG,CAAC,MAAM,EAAE,GAAG;gBACb,IAAI,GAAG,KAAK,MAAM;oBAAE,OAAO,CAAC,GAAW,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;gBACpF,IAAI,GAAG,KAAK,UAAU;oBACpB,OAAO,KAAK,EAAE,IAAY,EAAE,EAAE;wBAC5B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;wBAC1C,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;4BACjC,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,oBAAoB,CAAC,KAAK,CAAC;gCAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;4BAC7E,sEAAsE;4BACtE,MAAM,YAAY,GAAG,MAAM,CACzB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,wCAAwC,CACpE,CAAC,YAAY,CAAC;4BACf,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC;gCAC7B,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;oCACvC,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;oCACjC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;wCAC7B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAChC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC;4CACtD,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CACxC,CAAC;gCACN,CAAC;wBACL,CAAC;wBACD,OAAO,KAAK,CAAC;oBACf,CAAC,CAAC;gBACJ,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;gBACvC,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YAClE,CAAC;SACF,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QACpD,IAAI,OAAO,EAAE,MAAM,KAAK,MAAM;YAAE,MAAM,IAAI,cAAc,CAAC,0BAA0B,CAAC,CAAC;QACrF,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5D,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7D,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,cAAc,CAAC,kBAAkB,CAAC,CAAC;QAC3D,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,KAAK,YAAY,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,aAAa,CAAC,CAAC;IACpF,CAAC;YAAS,CAAC;QACT,MAAM,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC1C,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,MAAoB;IAC3D,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAC5E,OAAO,IAAI,OAAO,CAAC,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE;YACzE,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC;SAC7C,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,GAAG,EAAE;YAClB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC9C,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,GAAG,EAAE;YACjB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtB,MAAM,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACzC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,OAAgB,EAAE,EAAE;YACzC,MAAM,EAAE,CAAC;YACT,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;YAC9B,IAAI,KAAK,CAAC,EAAE,KAAK,IAAI;gBAAE,aAAa,CAAC,KAAK,CAAC,OAAmB,CAAC,CAAC;;gBAE9D,MAAM,CAAC,IAAI,cAAc,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAChG,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;YACvB,MAAM,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,cAAc,CAAC,qBAAqB,CAAC,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;YACvB,MAAM,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,cAAc,CAAC,qBAAqB,CAAC,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QACH,IAAI,MAAM,EAAE,OAAO;YAAE,KAAK,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAc;IAC9C,IAAI,MAAqE,CAAC;IAC1E,IAAI,CAAC;QACH,MAAM,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,GAAG;YACP,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,KAAK,YAAY,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,qBAAqB;SAC3E,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YACvC,IAAI,CAAC,OAAO,CAAC,IAAI;gBAAE,OAAO,MAAM,CAAC,IAAI,cAAc,CAAC,qBAAqB,CAAC,CAAC,CAAC;YAC5E,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;IACzB,CAAC;AACH,CAAC;AAED,IACE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,YAAY;IAChC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACf,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC;IAE3D,MAAM,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ApiClient } from "../api/client.js";
|
|
2
|
+
import type { ReportProgress } from "./types.js";
|
|
3
|
+
export interface PollResult {
|
|
4
|
+
status: "idle" | "complete" | "partial" | "failed";
|
|
5
|
+
media: number;
|
|
6
|
+
error?: string;
|
|
7
|
+
errorStatus?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function authenticatedClient(): ApiClient;
|
|
10
|
+
export declare function processOne(client: ApiClient, parent?: AbortSignal, progress?: ReportProgress): Promise<PollResult>;
|
|
11
|
+
export declare function runOnce(signal?: AbortSignal, progress?: ReportProgress): Promise<PollResult>;
|
|
12
|
+
export declare function watchConnector(signal: AbortSignal, json?: boolean): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/connector/runtime.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAkB,MAAM,kBAAkB,CAAC;AAM7D,OAAO,KAAK,EAAqC,cAAc,EAAQ,MAAM,YAAY,CAAC;AAE1F,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,mBAAmB,IAAI,SAAS,CAI/C;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,SAAS,EACjB,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,UAAU,CAAC,CAuGrB;AAiCD,wBAAsB,OAAO,CAC3B,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,UAAU,CAAC,CAGrB;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BrF"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
5
|
+
import { ApiClient, ApiClientError } from "../api/client.js";
|
|
6
|
+
import { getApiKey } from "../config.js";
|
|
7
|
+
import { ConnectorError } from "./core.js";
|
|
8
|
+
import { downloadMedia, makePoster } from "./download.js";
|
|
9
|
+
import { ConnectorLogger, connectorErrorHint } from "./log.js";
|
|
10
|
+
import { readPost } from "./opencli.js";
|
|
11
|
+
export function authenticatedClient() {
|
|
12
|
+
const key = getApiKey();
|
|
13
|
+
if (!key)
|
|
14
|
+
throw new ApiClientError(401, "Not authenticated. Run `zhe login` first.");
|
|
15
|
+
return new ApiClient(key);
|
|
16
|
+
}
|
|
17
|
+
export async function processOne(client, parent, progress) {
|
|
18
|
+
const { job } = await client.claimXJob(parent);
|
|
19
|
+
if (!job)
|
|
20
|
+
return { status: "idle", media: 0 };
|
|
21
|
+
progress?.({
|
|
22
|
+
stage: "claim",
|
|
23
|
+
message: `Link #${job.linkId} · X post ${job.postId} · attempt ${job.attempts}`,
|
|
24
|
+
});
|
|
25
|
+
const controller = new AbortController();
|
|
26
|
+
const signal = parent ? AbortSignal.any([parent, controller.signal]) : controller.signal;
|
|
27
|
+
let renewing;
|
|
28
|
+
const heartbeat = setInterval(() => {
|
|
29
|
+
if (renewing)
|
|
30
|
+
return;
|
|
31
|
+
renewing = client
|
|
32
|
+
.connectorAction(job, { action: "renew" }, signal)
|
|
33
|
+
.then(() => { })
|
|
34
|
+
.catch(() => controller.abort())
|
|
35
|
+
.finally(() => {
|
|
36
|
+
renewing = undefined;
|
|
37
|
+
});
|
|
38
|
+
}, 30_000);
|
|
39
|
+
let dir;
|
|
40
|
+
let archived = 0;
|
|
41
|
+
let incomplete = false;
|
|
42
|
+
try {
|
|
43
|
+
dir = await mkdtemp(join(tmpdir(), "zhe-connector-"));
|
|
44
|
+
progress?.({ stage: "read", message: "Reading the saved post through the local X session" });
|
|
45
|
+
const capture = await readPost(job.postId, signal);
|
|
46
|
+
progress?.({
|
|
47
|
+
stage: "capture",
|
|
48
|
+
message: `Saving ${capture.tweet.text.length} characters · ${capture.media.length} media found`,
|
|
49
|
+
total: capture.media.length,
|
|
50
|
+
});
|
|
51
|
+
await client.connectorAction(job, { action: "capture", capture }, signal);
|
|
52
|
+
for (const [index, media] of capture.media.entries()) {
|
|
53
|
+
signal.throwIfAborted();
|
|
54
|
+
const reportMedia = (event) => progress?.({
|
|
55
|
+
...event,
|
|
56
|
+
current: index + 1,
|
|
57
|
+
total: capture.media.length,
|
|
58
|
+
message: `${media.type} ${index + 1}/${capture.media.length} · ${event.message}`,
|
|
59
|
+
});
|
|
60
|
+
try {
|
|
61
|
+
reportMedia({ stage: "download", message: "Connecting to X media" });
|
|
62
|
+
const file = await downloadMedia(media, dir, signal, (phase, received, bytes) => {
|
|
63
|
+
reportMedia({
|
|
64
|
+
stage: phase,
|
|
65
|
+
message: phase === "download" ? "Downloading" : "Verifying format and full decode",
|
|
66
|
+
received,
|
|
67
|
+
bytes,
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
const kind = media.type === "PHOTO" ? "photo" : "video";
|
|
71
|
+
if (!(await archive(client, job, media.id, kind, file, signal, reportMedia)))
|
|
72
|
+
continue;
|
|
73
|
+
media.width = file.width;
|
|
74
|
+
media.height = file.height;
|
|
75
|
+
media.duration = file.duration;
|
|
76
|
+
archived++;
|
|
77
|
+
if (kind === "video") {
|
|
78
|
+
reportMedia({ stage: "poster", message: "Generating video poster" });
|
|
79
|
+
const poster = await makePoster(file.path, signal);
|
|
80
|
+
if (poster)
|
|
81
|
+
await archive(client, job, media.id, "poster", poster, signal, reportMedia);
|
|
82
|
+
else
|
|
83
|
+
reportMedia({ stage: "warning", message: "Poster unavailable; video is archived" });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
if (signal.aborted ||
|
|
88
|
+
(error instanceof ApiClientError && [401, 403, 409].includes(error.status)))
|
|
89
|
+
throw error;
|
|
90
|
+
incomplete = true;
|
|
91
|
+
reportMedia({ stage: "warning", message: connectorErrorHint(error) });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
signal.throwIfAborted();
|
|
95
|
+
capture.tweet.media = capture.media;
|
|
96
|
+
progress?.({
|
|
97
|
+
stage: "publish",
|
|
98
|
+
message: `Saving the enriched post · ${archived}/${capture.media.length} media archived`,
|
|
99
|
+
});
|
|
100
|
+
await client.connectorAction(job, { action: "capture", capture }, signal);
|
|
101
|
+
await client.connectorAction(job, { action: "complete" }, signal);
|
|
102
|
+
return { status: incomplete ? "partial" : "complete", media: archived };
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
const code = error instanceof ConnectorError
|
|
106
|
+
? error.code
|
|
107
|
+
: signal.aborted
|
|
108
|
+
? "interrupted"
|
|
109
|
+
: "connector_error";
|
|
110
|
+
await client.connectorAction(job, { action: "fail", code }).catch(() => { });
|
|
111
|
+
return {
|
|
112
|
+
status: "failed",
|
|
113
|
+
media: archived,
|
|
114
|
+
error: code,
|
|
115
|
+
...(error instanceof ApiClientError ? { errorStatus: error.status } : {}),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
clearInterval(heartbeat);
|
|
120
|
+
controller.abort();
|
|
121
|
+
await renewing;
|
|
122
|
+
if (dir)
|
|
123
|
+
await rm(dir, { recursive: true, force: true });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function archive(client, job, mediaId, kind, file, signal, progress) {
|
|
127
|
+
progress?.({ stage: "upload", message: `Preparing ${kind} archive` });
|
|
128
|
+
const { asset } = await client.connectorAction(job, {
|
|
129
|
+
action: "reserve",
|
|
130
|
+
media: { mediaId, kind, size: file.size, mime: file.mime, sha256: file.sha256 },
|
|
131
|
+
}, signal);
|
|
132
|
+
if (asset.skipped) {
|
|
133
|
+
progress?.({ stage: "skipped", message: `${kind} was explicitly deleted; keeping it deleted` });
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
if (!asset.uploaded) {
|
|
137
|
+
progress?.({ stage: "upload", message: `Uploading ${kind} to Zhe`, bytes: file.size });
|
|
138
|
+
await client.uploadXMedia(job, asset, file, signal);
|
|
139
|
+
progress?.({ stage: "uploaded", message: `${kind} upload confirmed`, bytes: file.size });
|
|
140
|
+
}
|
|
141
|
+
else
|
|
142
|
+
progress?.({ stage: "saved", message: `${kind} already archived; reusing the saved file` });
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
export async function runOnce(signal, progress) {
|
|
146
|
+
// Read the shared CLI configuration on each poll, so logout/rotation takes effect.
|
|
147
|
+
return processOne(authenticatedClient(), signal, progress);
|
|
148
|
+
}
|
|
149
|
+
export async function watchConnector(signal, json = false) {
|
|
150
|
+
const log = new ConnectorLogger(json);
|
|
151
|
+
const activity = setInterval(() => log.tick(), 10_000);
|
|
152
|
+
log.start();
|
|
153
|
+
try {
|
|
154
|
+
while (!signal.aborted) {
|
|
155
|
+
const started = Date.now();
|
|
156
|
+
try {
|
|
157
|
+
const client = authenticatedClient();
|
|
158
|
+
// Queue statistics are optional; a failed status lookup must not block enrichment.
|
|
159
|
+
const status = await client.connectorStatus(signal).catch(() => undefined);
|
|
160
|
+
if (signal.aborted)
|
|
161
|
+
break;
|
|
162
|
+
if (status)
|
|
163
|
+
log.queue(status);
|
|
164
|
+
log.result(await processOne(client, signal, log.progress), Date.now() - started, !signal.aborted);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
if (!signal.aborted)
|
|
168
|
+
log.offline(error);
|
|
169
|
+
}
|
|
170
|
+
if (!signal.aborted)
|
|
171
|
+
await delay(20_000, undefined, { signal }).catch(() => { });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
clearInterval(activity);
|
|
176
|
+
log.stop();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/connector/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface XJob {
|
|
2
|
+
linkId: number;
|
|
3
|
+
userId: string;
|
|
4
|
+
postId: string;
|
|
5
|
+
sourceUrl: string;
|
|
6
|
+
leaseToken: string;
|
|
7
|
+
leaseUntil: number;
|
|
8
|
+
attempts: number;
|
|
9
|
+
}
|
|
10
|
+
export interface MediaReservation {
|
|
11
|
+
id: string;
|
|
12
|
+
key: string;
|
|
13
|
+
uploaded: boolean;
|
|
14
|
+
skipped?: false;
|
|
15
|
+
}
|
|
16
|
+
export interface DownloadedMedia {
|
|
17
|
+
path: string;
|
|
18
|
+
size: number;
|
|
19
|
+
sha256: string;
|
|
20
|
+
mime: string;
|
|
21
|
+
width?: number | undefined;
|
|
22
|
+
height?: number | undefined;
|
|
23
|
+
duration?: number | undefined;
|
|
24
|
+
}
|
|
25
|
+
export interface ConnectorStatus {
|
|
26
|
+
states: {
|
|
27
|
+
state: string;
|
|
28
|
+
count: number;
|
|
29
|
+
}[];
|
|
30
|
+
keyPrefix: string;
|
|
31
|
+
expiresAt: number;
|
|
32
|
+
}
|
|
33
|
+
export interface ConnectorProgress {
|
|
34
|
+
stage: "claim" | "read" | "capture" | "download" | "verify" | "upload" | "uploaded" | "poster" | "saved" | "skipped" | "warning" | "publish";
|
|
35
|
+
message: string;
|
|
36
|
+
current?: number;
|
|
37
|
+
total?: number;
|
|
38
|
+
received?: number;
|
|
39
|
+
bytes?: number;
|
|
40
|
+
}
|
|
41
|
+
export type ReportProgress = (event: ConnectorProgress) => void;
|
|
42
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/connector/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,IAAI;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AACD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EACD,OAAO,GACP,MAAM,GACN,SAAS,GACT,UAAU,GACV,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,OAAO,GACP,SAAS,GACT,SAAS,GACT,SAAS,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/connector/types.ts"],"names":[],"mappings":""}
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* zhe CLI — Manage zhe.to short links
|
|
4
4
|
*/
|
|
5
|
-
import { defineCommand, runMain } from "@nocoo/cli
|
|
5
|
+
import { defineCommand, runMain } from "@nocoo/base-cli";
|
|
6
|
+
import { connectorCommand } from "./commands/connector.js";
|
|
6
7
|
import { createCommand } from "./commands/create.js";
|
|
7
8
|
import { deleteCommand } from "./commands/delete.js";
|
|
8
9
|
import { folderCommand } from "./commands/folder.js";
|
|
@@ -39,6 +40,7 @@ const main = defineCommand({
|
|
|
39
40
|
update: updateCommand,
|
|
40
41
|
delete: deleteCommand,
|
|
41
42
|
open: openCommand,
|
|
43
|
+
connector: connectorCommand,
|
|
42
44
|
},
|
|
43
45
|
});
|
|
44
46
|
runMain(main);
|