Merge 781fc7b2dd into 9025da2296
This commit is contained in:
commit
e1b0a4effd
@ -8,16 +8,62 @@ export type TelegramFileInfo = {
|
|||||||
file_path?: string;
|
file_path?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function getTelegramFile(token: string, fileId: string): Promise<TelegramFileInfo> {
|
export type TelegramDownloadOptions = {
|
||||||
const res = await fetch(
|
fetchImpl?: typeof fetch;
|
||||||
`https://api.telegram.org/bot${token}/getFile?file_id=${encodeURIComponent(fileId)}`,
|
};
|
||||||
);
|
|
||||||
if (!res.ok) {
|
export class TelegramDownloadError extends Error {
|
||||||
throw new Error(`getFile failed: ${res.status} ${res.statusText}`);
|
readonly code: "fetch_failed" | "http_error" | "api_error";
|
||||||
|
|
||||||
|
constructor(code: "fetch_failed" | "http_error" | "api_error", message: string) {
|
||||||
|
super(message);
|
||||||
|
this.code = code;
|
||||||
|
this.name = "TelegramDownloadError";
|
||||||
}
|
}
|
||||||
const json = (await res.json()) as { ok: boolean; result?: TelegramFileInfo };
|
}
|
||||||
|
|
||||||
|
export async function getTelegramFile(
|
||||||
|
token: string,
|
||||||
|
fileId: string,
|
||||||
|
options?: TelegramDownloadOptions,
|
||||||
|
): Promise<TelegramFileInfo> {
|
||||||
|
const fetcher = options?.fetchImpl ?? globalThis.fetch;
|
||||||
|
if (!fetcher) {
|
||||||
|
throw new TelegramDownloadError(
|
||||||
|
"fetch_failed",
|
||||||
|
"fetch is not available; set channels.telegram.proxy in config",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let res: Response;
|
||||||
|
try {
|
||||||
|
res = await fetcher(
|
||||||
|
`https://api.telegram.org/bot${token}/getFile?file_id=${encodeURIComponent(fileId)}`,
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
throw new TelegramDownloadError(
|
||||||
|
"fetch_failed",
|
||||||
|
`Failed to fetch Telegram file info: ${err instanceof Error ? err.message : String(err)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new TelegramDownloadError(
|
||||||
|
"http_error",
|
||||||
|
`getFile failed: ${res.status} ${res.statusText}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const json = (await res.json()) as {
|
||||||
|
ok: boolean;
|
||||||
|
result?: TelegramFileInfo;
|
||||||
|
description?: string;
|
||||||
|
};
|
||||||
if (!json.ok || !json.result?.file_path) {
|
if (!json.ok || !json.result?.file_path) {
|
||||||
throw new Error("getFile returned no file_path");
|
throw new TelegramDownloadError(
|
||||||
|
"api_error",
|
||||||
|
json.description ?? "getFile returned no file_path",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return json.result;
|
return json.result;
|
||||||
}
|
}
|
||||||
@ -26,13 +72,39 @@ export async function downloadTelegramFile(
|
|||||||
token: string,
|
token: string,
|
||||||
info: TelegramFileInfo,
|
info: TelegramFileInfo,
|
||||||
maxBytes?: number,
|
maxBytes?: number,
|
||||||
|
options?: TelegramDownloadOptions,
|
||||||
): Promise<SavedMedia> {
|
): Promise<SavedMedia> {
|
||||||
if (!info.file_path) throw new Error("file_path missing");
|
if (!info.file_path) {
|
||||||
const url = `https://api.telegram.org/file/bot${token}/${info.file_path}`;
|
throw new TelegramDownloadError("api_error", "file_path missing");
|
||||||
const res = await fetch(url);
|
|
||||||
if (!res.ok || !res.body) {
|
|
||||||
throw new Error(`Failed to download telegram file: HTTP ${res.status}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fetcher = options?.fetchImpl ?? globalThis.fetch;
|
||||||
|
if (!fetcher) {
|
||||||
|
throw new TelegramDownloadError(
|
||||||
|
"fetch_failed",
|
||||||
|
"fetch is not available; set channels.telegram.proxy in config",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = `https://api.telegram.org/file/bot${token}/${info.file_path}`;
|
||||||
|
|
||||||
|
let res: Response;
|
||||||
|
try {
|
||||||
|
res = await fetcher(url);
|
||||||
|
} catch (err) {
|
||||||
|
throw new TelegramDownloadError(
|
||||||
|
"fetch_failed",
|
||||||
|
`Failed to download Telegram file: ${err instanceof Error ? err.message : String(err)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res.ok || !res.body) {
|
||||||
|
throw new TelegramDownloadError(
|
||||||
|
"http_error",
|
||||||
|
`Failed to download telegram file: HTTP ${res.status}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const array = Buffer.from(await res.arrayBuffer());
|
const array = Buffer.from(await res.arrayBuffer());
|
||||||
const mime = await detectMime({
|
const mime = await detectMime({
|
||||||
buffer: array,
|
buffer: array,
|
||||||
@ -40,7 +112,7 @@ export async function downloadTelegramFile(
|
|||||||
filePath: info.file_path,
|
filePath: info.file_path,
|
||||||
});
|
});
|
||||||
// save with inbound subdir
|
// save with inbound subdir
|
||||||
const saved = await saveMediaBuffer(array, mime, "inbound", maxBytes, info.file_path);
|
const saved = await saveMediaBuffer(array, mime, "inbound", maxBytes);
|
||||||
// Ensure extension matches mime if possible
|
// Ensure extension matches mime if possible
|
||||||
if (!saved.contentType && mime) saved.contentType = mime;
|
if (!saved.contentType && mime) saved.contentType = mime;
|
||||||
return saved;
|
return saved;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user