MCPcopy Create free account
hub / github.com/CreminiAI/skillpack / downloadAndSaveAttachment

Function downloadAndSaveAttachment

src/runtime/adapters/attachment-utils.ts:64–106  ·  view source on GitHub ↗
(
  rootDir: string,
  channelId: string,
  url: string,
  filename: string,
  mimeType?: string,
  headers?: Record<string, string>,
)

Source from the content-addressed store, hash-verified

62 * Download a file from a URL and save it as an attachment.
63 */
64export async function downloadAndSaveAttachment(
65 rootDir: string,
66 channelId: string,
67 url: string,
68 filename: string,
69 mimeType?: string,
70 headers?: Record<string, string>,
71): Promise<ChannelAttachment> {
72 const dir = getAttachmentDir(rootDir, channelId);
73 fs.mkdirSync(dir, { recursive: true });
74
75 const ts = Date.now();
76 const safeName = sanitizeFilename(filename);
77 const storedName = `${ts}-${safeName}`;
78 const fullPath = path.join(dir, storedName);
79
80 const response = await fetch(url, { headers });
81 if (!response.ok) {
82 throw new Error(
83 `Failed to download attachment from ${url}: ${response.status} ${response.statusText}`,
84 );
85 }
86
87 const body = response.body;
88 if (!body) {
89 throw new Error(`Empty response body when downloading ${url}`);
90 }
91
92 const nodeStream = Readable.fromWeb(body as any);
93 const writeStream = fs.createWriteStream(fullPath);
94 await pipeline(nodeStream, writeStream);
95
96 const stats = fs.statSync(fullPath);
97 const detectedMime =
98 mimeType || response.headers.get("content-type")?.split(";")[0] || undefined;
99
100 return {
101 filename,
102 localPath: fullPath,
103 mimeType: detectedMime,
104 size: stats.size,
105 };
106}
107
108// ---------------------------------------------------------------------------
109// Formatting helpers

Callers 2

downloadTelegramFileMethod · 0.85
extractSlackFilesMethod · 0.85

Calls 2

getAttachmentDirFunction · 0.85
sanitizeFilenameFunction · 0.85

Tested by

no test coverage detected