refactor(src): split oversized modules
This commit is contained in:
88
src/slack/monitor/media.ts
Normal file
88
src/slack/monitor/media.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import type { WebClient as SlackWebClient } from "@slack/web-api";
|
||||
|
||||
import type { FetchLike } from "../../media/fetch.js";
|
||||
import { fetchRemoteMedia } from "../../media/fetch.js";
|
||||
import { saveMediaBuffer } from "../../media/store.js";
|
||||
import type { SlackFile } from "../types.js";
|
||||
|
||||
export async function resolveSlackMedia(params: {
|
||||
files?: SlackFile[];
|
||||
token: string;
|
||||
maxBytes: number;
|
||||
}): Promise<{
|
||||
path: string;
|
||||
contentType?: string;
|
||||
placeholder: string;
|
||||
} | null> {
|
||||
const files = params.files ?? [];
|
||||
for (const file of files) {
|
||||
const url = file.url_private_download ?? file.url_private;
|
||||
if (!url) continue;
|
||||
try {
|
||||
const fetchImpl: FetchLike = (input, init) => {
|
||||
const headers = new Headers(init?.headers);
|
||||
headers.set("Authorization", `Bearer ${params.token}`);
|
||||
return fetch(input, { ...init, headers });
|
||||
};
|
||||
const fetched = await fetchRemoteMedia({
|
||||
url,
|
||||
fetchImpl,
|
||||
filePathHint: file.name,
|
||||
});
|
||||
if (fetched.buffer.byteLength > params.maxBytes) continue;
|
||||
const saved = await saveMediaBuffer(
|
||||
fetched.buffer,
|
||||
fetched.contentType ?? file.mimetype,
|
||||
"inbound",
|
||||
params.maxBytes,
|
||||
);
|
||||
const label = fetched.fileName ?? file.name;
|
||||
return {
|
||||
path: saved.path,
|
||||
contentType: saved.contentType,
|
||||
placeholder: label ? `[Slack file: ${label}]` : "[Slack file]",
|
||||
};
|
||||
} catch {
|
||||
// Ignore download failures and fall through to the next file.
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export type SlackThreadStarter = {
|
||||
text: string;
|
||||
userId?: string;
|
||||
ts?: string;
|
||||
};
|
||||
|
||||
const THREAD_STARTER_CACHE = new Map<string, SlackThreadStarter>();
|
||||
|
||||
export async function resolveSlackThreadStarter(params: {
|
||||
channelId: string;
|
||||
threadTs: string;
|
||||
client: SlackWebClient;
|
||||
}): Promise<SlackThreadStarter | null> {
|
||||
const cacheKey = `${params.channelId}:${params.threadTs}`;
|
||||
const cached = THREAD_STARTER_CACHE.get(cacheKey);
|
||||
if (cached) return cached;
|
||||
try {
|
||||
const response = (await params.client.conversations.replies({
|
||||
channel: params.channelId,
|
||||
ts: params.threadTs,
|
||||
limit: 1,
|
||||
inclusive: true,
|
||||
})) as { messages?: Array<{ text?: string; user?: string; ts?: string }> };
|
||||
const message = response?.messages?.[0];
|
||||
const text = (message?.text ?? "").trim();
|
||||
if (!message || !text) return null;
|
||||
const starter: SlackThreadStarter = {
|
||||
text,
|
||||
userId: message.user,
|
||||
ts: message.ts,
|
||||
};
|
||||
THREAD_STARTER_CACHE.set(cacheKey, starter);
|
||||
return starter;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user