Hydrate Telegram avatars on demand in frontend API
This commit is contained in:
@@ -14,6 +14,29 @@ type TelegramFileMeta = {
|
||||
file_path?: string;
|
||||
};
|
||||
|
||||
type TelegramChatPhoto = {
|
||||
small_file_id?: string;
|
||||
big_file_id?: string;
|
||||
};
|
||||
|
||||
type TelegramGetChatResponse = {
|
||||
ok?: boolean;
|
||||
result?: {
|
||||
photo?: TelegramChatPhoto;
|
||||
};
|
||||
};
|
||||
|
||||
type TelegramProfilePhotoSize = {
|
||||
file_id?: string;
|
||||
};
|
||||
|
||||
type TelegramGetUserProfilePhotosResponse = {
|
||||
ok?: boolean;
|
||||
result?: {
|
||||
photos?: TelegramProfilePhotoSize[][];
|
||||
};
|
||||
};
|
||||
|
||||
function parseTelegramFileId(avatarUrl: string | null | undefined) {
|
||||
const raw = String(avatarUrl ?? "").trim();
|
||||
if (!raw.startsWith(TELEGRAM_FILE_MARKER)) return null;
|
||||
@@ -25,6 +48,22 @@ function sanitizeCacheKey(input: string) {
|
||||
return input.replace(/[^a-zA-Z0-9._-]/g, "_");
|
||||
}
|
||||
|
||||
async function fetchTelegramAvatarFileIdByExternalId(externalId: string) {
|
||||
const getChatRes = await telegramBotApi<TelegramGetChatResponse["result"]>("getChat", {
|
||||
chat_id: externalId,
|
||||
});
|
||||
const fromChat = String(getChatRes?.photo?.small_file_id ?? getChatRes?.photo?.big_file_id ?? "").trim();
|
||||
if (fromChat) return fromChat;
|
||||
|
||||
const getUserPhotosRes = await telegramBotApi<TelegramGetUserProfilePhotosResponse["result"]>("getUserProfilePhotos", {
|
||||
user_id: externalId,
|
||||
limit: 1,
|
||||
});
|
||||
const firstPhotoSizes = Array.isArray(getUserPhotosRes?.photos?.[0]) ? getUserPhotosRes.photos[0] : [];
|
||||
const candidate = String(firstPhotoSizes.at(-1)?.file_id ?? firstPhotoSizes[0]?.file_id ?? "").trim();
|
||||
return candidate || null;
|
||||
}
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const auth = await getAuthContext(event);
|
||||
const query = getQuery(event);
|
||||
@@ -48,9 +87,36 @@ export default defineEventHandler(async (event) => {
|
||||
throw createError({ statusCode: 404, statusMessage: "contact not found" });
|
||||
}
|
||||
|
||||
const fileId = parseTelegramFileId(contact.avatarUrl);
|
||||
let fileId = parseTelegramFileId(contact.avatarUrl);
|
||||
if (!fileId) {
|
||||
throw createError({ statusCode: 404, statusMessage: "telegram avatar is missing" });
|
||||
const identity = await prisma.omniContactIdentity.findFirst({
|
||||
where: {
|
||||
teamId: auth.teamId,
|
||||
contactId,
|
||||
channel: "TELEGRAM",
|
||||
},
|
||||
select: {
|
||||
externalId: true,
|
||||
},
|
||||
orderBy: {
|
||||
updatedAt: "desc",
|
||||
},
|
||||
});
|
||||
|
||||
if (!identity?.externalId) {
|
||||
throw createError({ statusCode: 404, statusMessage: "telegram identity is missing" });
|
||||
}
|
||||
|
||||
const fetchedFileId = await fetchTelegramAvatarFileIdByExternalId(identity.externalId);
|
||||
if (!fetchedFileId) {
|
||||
throw createError({ statusCode: 404, statusMessage: "telegram avatar is missing" });
|
||||
}
|
||||
|
||||
fileId = fetchedFileId;
|
||||
await prisma.contact.update({
|
||||
where: { id: contactId },
|
||||
data: { avatarUrl: `${TELEGRAM_FILE_MARKER}${fileId}` },
|
||||
});
|
||||
}
|
||||
|
||||
const cacheKey = sanitizeCacheKey(fileId);
|
||||
|
||||
Reference in New Issue
Block a user