64 lines
2.0 KiB
TypeScript
64 lines
2.0 KiB
TypeScript
import { getRouterParam, setHeader } from "h3";
|
|
import { getAuthContext } from "../../../../utils/auth";
|
|
import { requireTelegramBotToken, telegramApiBase, telegramBotApi } from "../../../../utils/telegram";
|
|
|
|
type TelegramProfilePhotoSize = {
|
|
file_id?: string;
|
|
};
|
|
|
|
type TelegramUserProfilePhotosResult = {
|
|
photos?: TelegramProfilePhotoSize[][];
|
|
};
|
|
|
|
type TelegramGetFileResult = {
|
|
file_path?: string;
|
|
};
|
|
|
|
function parseUserId(input: string) {
|
|
if (!/^\d+$/.test(input)) return null;
|
|
const value = Number(input);
|
|
if (!Number.isSafeInteger(value) || value <= 0) return null;
|
|
return value;
|
|
}
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
await getAuthContext(event);
|
|
|
|
const rawUserId = String(getRouterParam(event, "userId") ?? "").trim();
|
|
const userId = parseUserId(rawUserId);
|
|
if (!userId) {
|
|
throw createError({ statusCode: 400, statusMessage: "invalid telegram user id" });
|
|
}
|
|
|
|
const profile = await telegramBotApi<TelegramUserProfilePhotosResult>("getUserProfilePhotos", {
|
|
user_id: userId,
|
|
limit: 1,
|
|
});
|
|
|
|
const sizes = profile.photos?.[0] ?? [];
|
|
const best = sizes[sizes.length - 1];
|
|
const fileId = String(best?.file_id ?? "").trim();
|
|
if (!fileId) {
|
|
throw createError({ statusCode: 404, statusMessage: "avatar not found" });
|
|
}
|
|
|
|
const fileMeta = await telegramBotApi<TelegramGetFileResult>("getFile", { file_id: fileId });
|
|
const filePath = String(fileMeta.file_path ?? "").trim();
|
|
if (!filePath) {
|
|
throw createError({ statusCode: 404, statusMessage: "avatar path not found" });
|
|
}
|
|
|
|
const token = requireTelegramBotToken();
|
|
const upstream = await fetch(`${telegramApiBase()}/file/bot${token}/${filePath}`);
|
|
if (!upstream.ok) {
|
|
throw createError({ statusCode: 502, statusMessage: "failed to load telegram avatar" });
|
|
}
|
|
|
|
const contentType = upstream.headers.get("content-type") || "image/jpeg";
|
|
const buffer = Buffer.from(await upstream.arrayBuffer());
|
|
|
|
setHeader(event, "content-type", contentType);
|
|
setHeader(event, "cache-control", "private, max-age=300");
|
|
return buffer;
|
|
});
|