fix: make forwardToStorage fully dynamic based on fileType
- Replace forceDocument boolean with fileType string in forwardToStorage - Dynamically call matching sendPhoto, sendAudio, sendVideo, sendVoice, sendAnimation, sendSticker, or sendDocument Telegraf API method - Correctly extract uploaded file details based on what Telegram returned - Fixes IMAGE_PROCESS_FAILED 500 error when uploading ogg audio, video, sticker, or voice notes via HTTP - Update upload.ts, bot.ts, and test suites to match the new dynamic signature Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
bf6d5f04c4
commit
525348b1f3
+1
-1
@@ -96,7 +96,7 @@ export const startBot = async (): Promise<Telegraf<Context>> => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await forwardToStorage(file_id, fileName);
|
const result = await forwardToStorage(file_id, fileName, fileType);
|
||||||
const publicId = nanoid();
|
const publicId = nanoid();
|
||||||
|
|
||||||
const uploaded = {
|
const uploaded = {
|
||||||
|
|||||||
+2
-10
@@ -88,11 +88,7 @@ const handleMultipartUpload = async (req: Request): Promise<Response> => {
|
|||||||
return Response.json({ error: `File size exceeds ${fileType} limit` }, { status: 400 });
|
return Response.json({ error: `File size exceeds ${fileType} limit` }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const isDocument =
|
const result = await forwardToStorage(fileBuffer, finalFileName, fileType);
|
||||||
finalFileName.endsWith('.pdf') ||
|
|
||||||
finalFileName.endsWith('.txt') ||
|
|
||||||
!['photo', 'video', 'audio', 'voice', 'animation'].includes(fileType);
|
|
||||||
const result = await forwardToStorage(fileBuffer, finalFileName, isDocument);
|
|
||||||
const bot = getBot();
|
const bot = getBot();
|
||||||
const fileInfo = (await bot.telegram.getFile(result.telegramFileId)) as any;
|
const fileInfo = (await bot.telegram.getFile(result.telegramFileId)) as any;
|
||||||
|
|
||||||
@@ -199,11 +195,7 @@ const handleJSONUpload = async (req: Request): Promise<Response> => {
|
|||||||
return Response.json({ error: `File size exceeds ${fileType} limit` }, { status: 400 });
|
return Response.json({ error: `File size exceeds ${fileType} limit` }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const isDocument =
|
const result = await forwardToStorage(fileBytes, finalFileName, fileType);
|
||||||
finalFileName.endsWith('.pdf') ||
|
|
||||||
finalFileName.endsWith('.txt') ||
|
|
||||||
!['photo', 'video', 'audio', 'voice', 'animation'].includes(fileType);
|
|
||||||
const result = await forwardToStorage(fileBytes, finalFileName, isDocument);
|
|
||||||
const bot = getBot();
|
const bot = getBot();
|
||||||
const fileInfo = (await bot.telegram.getFile(result.telegramFileId)) as any;
|
const fileInfo = (await bot.telegram.getFile(result.telegramFileId)) as any;
|
||||||
|
|
||||||
|
|||||||
+41
-6
@@ -20,15 +20,50 @@ interface TelegramFileInfo {
|
|||||||
export const forwardToStorage = async (
|
export const forwardToStorage = async (
|
||||||
fileChunk: any,
|
fileChunk: any,
|
||||||
fileName: string,
|
fileName: string,
|
||||||
forceDocument = false,
|
fileType: string,
|
||||||
): Promise<ForwardResult> => {
|
): Promise<ForwardResult> => {
|
||||||
try {
|
try {
|
||||||
const caption = forceDocument ? `📁 ${fileName}` : fileName;
|
|
||||||
const filePayload = { source: fileChunk, filename: fileName };
|
const filePayload = { source: fileChunk, filename: fileName };
|
||||||
const result: any = forceDocument
|
let result: any;
|
||||||
? await bot.telegram.sendDocument(config.storageChatId, filePayload, { caption })
|
|
||||||
: await bot.telegram.sendPhoto(config.storageChatId, filePayload, { caption });
|
if (fileType === 'photo') {
|
||||||
const uploadedFile = forceDocument ? result.document : result.photo?.slice(-1)[0];
|
result = await bot.telegram.sendPhoto(config.storageChatId, filePayload, {
|
||||||
|
caption: fileName,
|
||||||
|
});
|
||||||
|
} else if (fileType === 'audio') {
|
||||||
|
result = await bot.telegram.sendAudio(config.storageChatId, filePayload, {
|
||||||
|
caption: fileName,
|
||||||
|
});
|
||||||
|
} else if (fileType === 'video') {
|
||||||
|
result = await bot.telegram.sendVideo(config.storageChatId, filePayload, {
|
||||||
|
caption: fileName,
|
||||||
|
});
|
||||||
|
} else if (fileType === 'voice') {
|
||||||
|
result = await bot.telegram.sendVoice(config.storageChatId, filePayload, {
|
||||||
|
caption: fileName,
|
||||||
|
});
|
||||||
|
} else if (fileType === 'animation') {
|
||||||
|
result = await bot.telegram.sendAnimation(config.storageChatId, filePayload, {
|
||||||
|
caption: fileName,
|
||||||
|
});
|
||||||
|
} else if (fileType === 'sticker') {
|
||||||
|
result = await bot.telegram.sendSticker(config.storageChatId, filePayload);
|
||||||
|
} else {
|
||||||
|
result = await bot.telegram.sendDocument(config.storageChatId, filePayload, {
|
||||||
|
caption: `📁 ${fileName}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let uploadedFile: any;
|
||||||
|
if (result.document) uploadedFile = result.document;
|
||||||
|
else if (result.photo) uploadedFile = result.photo?.slice(-1)[0];
|
||||||
|
else if (result.video) uploadedFile = result.video;
|
||||||
|
else if (result.audio) uploadedFile = result.audio;
|
||||||
|
else if (result.voice) uploadedFile = result.voice;
|
||||||
|
else if (result.animation) uploadedFile = result.animation;
|
||||||
|
else if (result.sticker) uploadedFile = result.sticker;
|
||||||
|
else if (result.video_note) uploadedFile = result.video_note;
|
||||||
|
else uploadedFile = result[fileType];
|
||||||
|
|
||||||
logger.info('File forwarded to storage', { fileName, message: result.message_id });
|
logger.info('File forwarded to storage', { fileName, message: result.message_id });
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -132,7 +132,7 @@ describe('Telegram Bot Handler', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
await fileHandler(ctx);
|
await fileHandler(ctx);
|
||||||
expect(mockForwardToStorage).toHaveBeenCalledWith('doc_123', 'cv.pdf');
|
expect(mockForwardToStorage).toHaveBeenCalledWith('doc_123', 'cv.pdf', 'document');
|
||||||
expect(mockInsert).toHaveBeenCalled();
|
expect(mockInsert).toHaveBeenCalled();
|
||||||
expect(replyMock).toHaveBeenCalledWith(
|
expect(replyMock).toHaveBeenCalledWith(
|
||||||
expect.stringContaining('File berhasil diupload'),
|
expect.stringContaining('File berhasil diupload'),
|
||||||
@@ -233,7 +233,7 @@ describe('Telegram Bot Handler', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
await fileHandler(ctx);
|
await fileHandler(ctx);
|
||||||
expect(mockForwardToStorage).toHaveBeenCalledWith('sticker_123', 'file');
|
expect(mockForwardToStorage).toHaveBeenCalledWith('sticker_123', 'file', 'sticker');
|
||||||
expect(mockInsert).toHaveBeenCalled();
|
expect(mockInsert).toHaveBeenCalled();
|
||||||
expect(replyMock).toHaveBeenCalledWith(
|
expect(replyMock).toHaveBeenCalledWith(
|
||||||
expect.stringContaining('File berhasil diupload'),
|
expect.stringContaining('File berhasil diupload'),
|
||||||
@@ -263,7 +263,7 @@ describe('Telegram Bot Handler', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
await fileHandler(ctx);
|
await fileHandler(ctx);
|
||||||
expect(mockForwardToStorage).toHaveBeenCalledWith('video_note_123', 'file');
|
expect(mockForwardToStorage).toHaveBeenCalledWith('video_note_123', 'file', 'video_note');
|
||||||
expect(mockInsert).toHaveBeenCalled();
|
expect(mockInsert).toHaveBeenCalled();
|
||||||
expect(replyMock).toHaveBeenCalledWith(
|
expect(replyMock).toHaveBeenCalledWith(
|
||||||
expect.stringContaining('File berhasil diupload'),
|
expect.stringContaining('File berhasil diupload'),
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ describe('Telegram API Utilities', () => {
|
|||||||
it('should forward photo to storage chat and return file details', async () => {
|
it('should forward photo to storage chat and return file details', async () => {
|
||||||
const chunk = Buffer.from('fake photo data');
|
const chunk = Buffer.from('fake photo data');
|
||||||
const fileName = 'test_photo.jpg';
|
const fileName = 'test_photo.jpg';
|
||||||
const result = await forwardToStorage(chunk, fileName, false);
|
const result = await forwardToStorage(chunk, fileName, 'photo');
|
||||||
|
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
telegramFileId: 'photo_id_high',
|
telegramFileId: 'photo_id_high',
|
||||||
@@ -86,7 +86,7 @@ describe('Telegram API Utilities', () => {
|
|||||||
const chunk = Buffer.from('fake document data');
|
const chunk = Buffer.from('fake document data');
|
||||||
const fileName = 'document.pdf';
|
const fileName = 'document.pdf';
|
||||||
|
|
||||||
const result = await forwardToStorage(chunk, fileName, true);
|
const result = await forwardToStorage(chunk, fileName, 'document');
|
||||||
|
|
||||||
expect(bot.telegram.sendDocument).toHaveBeenCalledWith(
|
expect(bot.telegram.sendDocument).toHaveBeenCalledWith(
|
||||||
config.storageChatId,
|
config.storageChatId,
|
||||||
@@ -107,7 +107,7 @@ describe('Telegram API Utilities', () => {
|
|||||||
const chunk = Buffer.from('fake photo data');
|
const chunk = Buffer.from('fake photo data');
|
||||||
const fileName = 'test_photo.jpg';
|
const fileName = 'test_photo.jpg';
|
||||||
|
|
||||||
await expect(forwardToStorage(chunk, fileName, false)).rejects.toThrow(
|
await expect(forwardToStorage(chunk, fileName, 'photo')).rejects.toThrow(
|
||||||
'Telegram send failed',
|
'Telegram send failed',
|
||||||
);
|
);
|
||||||
expect(errorSpy).toHaveBeenCalledWith('Failed to forward file to storage', {
|
expect(errorSpy).toHaveBeenCalledWith('Failed to forward file to storage', {
|
||||||
|
|||||||
Reference in New Issue
Block a user