clawlabor 1.11.2 → 1.14.7

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.
@@ -0,0 +1,74 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const { attachmentPath, requestJson, requiredOption } = require("./shared");
4
+
5
+ function pickAttachment(files, options) {
6
+ const fileId = options["file-id"];
7
+ const filename = options.filename;
8
+ if (!fileId && !filename) {
9
+ throw new Error("Provide --file-id <file_id> or --filename <filename>");
10
+ }
11
+ if (fileId && filename) {
12
+ throw new Error("Use only one of --file-id or --filename");
13
+ }
14
+ if (fileId) {
15
+ const match = files.find((file) => file?.file_id === fileId);
16
+ if (!match) throw new Error(`Attachment not found for file_id: ${fileId}`);
17
+ return match;
18
+ }
19
+ const matches = files.filter((file) => file?.filename === filename);
20
+ if (matches.length === 0) throw new Error(`Attachment not found for filename: ${filename}`);
21
+ if (matches.length > 1) {
22
+ throw new Error(`Multiple attachments named ${filename}; use --file-id instead`);
23
+ }
24
+ return matches[0];
25
+ }
26
+
27
+ function outputPathForAttachment(file, options) {
28
+ const requested = options.out;
29
+ const safeName = path.basename(file.filename || file.file_id || "attachment");
30
+ if (!requested) return path.resolve(safeName);
31
+ const resolved = path.resolve(requested);
32
+ if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {
33
+ return path.join(resolved, safeName);
34
+ }
35
+ return resolved;
36
+ }
37
+
38
+ async function responseToBuffer(response) {
39
+ if (typeof response.arrayBuffer === "function") {
40
+ return Buffer.from(await response.arrayBuffer());
41
+ }
42
+ return Buffer.from(await response.text());
43
+ }
44
+
45
+ async function commandDownloadAttachment(options, deps) {
46
+ requiredOption(options, "entity");
47
+ requiredOption(options, "id");
48
+ const listing = await requestJson(deps, "GET", attachmentPath(options));
49
+ const files = Array.isArray(listing?.files) ? listing.files : [];
50
+ const file = pickAttachment(files, options);
51
+ if (!file.download_url) {
52
+ throw new Error(`Attachment has no download_url: ${file.file_id || file.filename}`);
53
+ }
54
+
55
+ const response = await deps.fetch(file.download_url, { method: "GET" });
56
+ const body = await responseToBuffer(response);
57
+ if (!response.ok) {
58
+ throw new Error(`Download failed (${response.status}): ${body.toString("utf8")}`);
59
+ }
60
+
61
+ const destination = outputPathForAttachment(file, options);
62
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
63
+ fs.writeFileSync(destination, body);
64
+ return JSON.stringify({
65
+ file_id: file.file_id || null,
66
+ filename: file.filename || null,
67
+ path: destination,
68
+ bytes: body.length,
69
+ });
70
+ }
71
+
72
+ module.exports = {
73
+ commandDownloadAttachment,
74
+ };