| | const fs = require('fs'); |
| | const path = require('path'); |
| | const sharp = require('sharp'); |
| | const { logger } = require('@librechat/data-schemas'); |
| | const { resizeImageBuffer } = require('../images/resize'); |
| | const { updateUser, updateFile } = require('~/models'); |
| | const { saveBufferToS3 } = require('./crud'); |
| |
|
| | const defaultBasePath = 'images'; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | async function uploadImageToS3({ |
| | req, |
| | file, |
| | file_id, |
| | endpoint, |
| | resolution = 'high', |
| | basePath = defaultBasePath, |
| | }) { |
| | try { |
| | const appConfig = req.config; |
| | const inputFilePath = file.path; |
| | const inputBuffer = await fs.promises.readFile(inputFilePath); |
| | const { |
| | buffer: resizedBuffer, |
| | width, |
| | height, |
| | } = await resizeImageBuffer(inputBuffer, resolution, endpoint); |
| | const extension = path.extname(inputFilePath); |
| | const userId = req.user.id; |
| |
|
| | let processedBuffer; |
| | let fileName = `${file_id}__${path.basename(inputFilePath)}`; |
| | const targetExtension = `.${appConfig.imageOutputType}`; |
| |
|
| | if (extension.toLowerCase() === targetExtension) { |
| | processedBuffer = resizedBuffer; |
| | } else { |
| | processedBuffer = await sharp(resizedBuffer).toFormat(appConfig.imageOutputType).toBuffer(); |
| | fileName = fileName.replace(new RegExp(path.extname(fileName) + '$'), targetExtension); |
| | if (!path.extname(fileName)) { |
| | fileName += targetExtension; |
| | } |
| | } |
| |
|
| | const downloadURL = await saveBufferToS3({ |
| | userId, |
| | buffer: processedBuffer, |
| | fileName, |
| | basePath, |
| | }); |
| | await fs.promises.unlink(inputFilePath); |
| | const bytes = Buffer.byteLength(processedBuffer); |
| | return { filepath: downloadURL, bytes, width, height }; |
| | } catch (error) { |
| | logger.error('[uploadImageToS3] Error uploading image to S3:', error.message); |
| | throw error; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | async function prepareImageURLS3(req, file) { |
| | try { |
| | const updatePromise = updateFile({ file_id: file.file_id }); |
| | return Promise.all([updatePromise, file.filepath]); |
| | } catch (error) { |
| | logger.error('[prepareImageURLS3] Error preparing image URL:', error.message); |
| | throw error; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | async function processS3Avatar({ buffer, userId, manual, agentId, basePath = defaultBasePath }) { |
| | try { |
| | const metadata = await sharp(buffer).metadata(); |
| | const extension = metadata.format === 'gif' ? 'gif' : 'png'; |
| | const timestamp = new Date().getTime(); |
| |
|
| | |
| | const fileName = agentId |
| | ? `agent-${agentId}-avatar-${timestamp}.${extension}` |
| | : `avatar-${timestamp}.${extension}`; |
| |
|
| | const downloadURL = await saveBufferToS3({ userId, buffer, fileName, basePath }); |
| |
|
| | |
| | if (manual === 'true' && !agentId) { |
| | await updateUser(userId, { avatar: downloadURL }); |
| | } |
| |
|
| | return downloadURL; |
| | } catch (error) { |
| | logger.error('[processS3Avatar] Error processing S3 avatar:', error.message); |
| | throw error; |
| | } |
| | } |
| |
|
| | module.exports = { |
| | uploadImageToS3, |
| | prepareImageURLS3, |
| | processS3Avatar, |
| | }; |
| |
|