Extract API endpoints for images
This commit is contained in:
parent
7dcd39c806
commit
b261c8c4a9
|
@ -29,7 +29,7 @@ let galleryMaxRows = 3;
|
||||||
* @returns {Promise<Array>} - Resolves with an array of gallery item objects, rejects on error.
|
* @returns {Promise<Array>} - Resolves with an array of gallery item objects, rejects on error.
|
||||||
*/
|
*/
|
||||||
async function getGalleryItems(url) {
|
async function getGalleryItems(url) {
|
||||||
const response = await fetch(`/listimgfiles/${url}`, {
|
const response = await fetch(`/api/images/list/${url}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getRequestHeaders(),
|
headers: getRequestHeaders(),
|
||||||
});
|
});
|
||||||
|
@ -201,7 +201,7 @@ async function uploadFile(file, url) {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await fetch('/uploadimage', {
|
const response = await fetch('/api/images/upload', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: headers,
|
headers: headers,
|
||||||
body: JSON.stringify(payload),
|
body: JSON.stringify(payload),
|
||||||
|
|
|
@ -996,7 +996,7 @@ export async function saveBase64AsFile(base64Data, characterName, filename = '',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Send the data URL to your backend using fetch
|
// Send the data URL to your backend using fetch
|
||||||
const response = await fetch('/uploadimage', {
|
const response = await fetch('/api/images/upload', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(requestBody),
|
body: JSON.stringify(requestBody),
|
||||||
headers: {
|
headers: {
|
||||||
|
|
93
server.js
93
server.js
|
@ -42,9 +42,6 @@ const {
|
||||||
getVersion,
|
getVersion,
|
||||||
getConfigValue,
|
getConfigValue,
|
||||||
color,
|
color,
|
||||||
clientRelativePath,
|
|
||||||
removeFileExtension,
|
|
||||||
getImages,
|
|
||||||
forwardFetchResponse,
|
forwardFetchResponse,
|
||||||
} = require('./src/util');
|
} = require('./src/util');
|
||||||
const { ensureThumbnailCache } = require('./src/endpoints/thumbnails');
|
const { ensureThumbnailCache } = require('./src/endpoints/thumbnails');
|
||||||
|
@ -244,89 +241,6 @@ app.post('/savemovingui', jsonParser, (request, response) => {
|
||||||
return response.sendStatus(200);
|
return response.sendStatus(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensure the directory for the provided file path exists.
|
|
||||||
* If not, it will recursively create the directory.
|
|
||||||
*
|
|
||||||
* @param {string} filePath - The full path of the file for which the directory should be ensured.
|
|
||||||
*/
|
|
||||||
function ensureDirectoryExistence(filePath) {
|
|
||||||
const dirname = path.dirname(filePath);
|
|
||||||
if (fs.existsSync(dirname)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
ensureDirectoryExistence(dirname);
|
|
||||||
fs.mkdirSync(dirname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Endpoint to handle image uploads.
|
|
||||||
* The image should be provided in the request body in base64 format.
|
|
||||||
* Optionally, a character name can be provided to save the image in a sub-folder.
|
|
||||||
*
|
|
||||||
* @route POST /uploadimage
|
|
||||||
* @param {Object} request.body - The request payload.
|
|
||||||
* @param {string} request.body.image - The base64 encoded image data.
|
|
||||||
* @param {string} [request.body.ch_name] - Optional character name to determine the sub-directory.
|
|
||||||
* @returns {Object} response - The response object containing the path where the image was saved.
|
|
||||||
*/
|
|
||||||
app.post('/uploadimage', jsonParser, async (request, response) => {
|
|
||||||
// Check for image data
|
|
||||||
if (!request.body || !request.body.image) {
|
|
||||||
return response.status(400).send({ error: 'No image data provided' });
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Extracting the base64 data and the image format
|
|
||||||
const splitParts = request.body.image.split(',');
|
|
||||||
const format = splitParts[0].split(';')[0].split('/')[1];
|
|
||||||
const base64Data = splitParts[1];
|
|
||||||
const validFormat = ['png', 'jpg', 'webp', 'jpeg', 'gif'].includes(format);
|
|
||||||
if (!validFormat) {
|
|
||||||
return response.status(400).send({ error: 'Invalid image format' });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructing filename and path
|
|
||||||
let filename;
|
|
||||||
if (request.body.filename) {
|
|
||||||
filename = `${removeFileExtension(request.body.filename)}.${format}`;
|
|
||||||
} else {
|
|
||||||
filename = `${Date.now()}.${format}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if character is defined, save to a sub folder for that character
|
|
||||||
let pathToNewFile = path.join(DIRECTORIES.userImages, sanitize(filename));
|
|
||||||
if (request.body.ch_name) {
|
|
||||||
pathToNewFile = path.join(DIRECTORIES.userImages, sanitize(request.body.ch_name), sanitize(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
ensureDirectoryExistence(pathToNewFile);
|
|
||||||
const imageBuffer = Buffer.from(base64Data, 'base64');
|
|
||||||
await fs.promises.writeFile(pathToNewFile, imageBuffer);
|
|
||||||
response.send({ path: clientRelativePath(pathToNewFile) });
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
response.status(500).send({ error: 'Failed to save the image' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.post('/listimgfiles/:folder', (req, res) => {
|
|
||||||
const directoryPath = path.join(process.cwd(), 'public/user/images/', sanitize(req.params.folder));
|
|
||||||
|
|
||||||
if (!fs.existsSync(directoryPath)) {
|
|
||||||
fs.mkdirSync(directoryPath, { recursive: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const images = getImages(directoryPath);
|
|
||||||
return res.send(images);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return res.status(500).send({ error: 'Unable to retrieve files' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
function cleanUploads() {
|
function cleanUploads() {
|
||||||
try {
|
try {
|
||||||
if (fs.existsSync(UPLOADS_PATH)) {
|
if (fs.existsSync(UPLOADS_PATH)) {
|
||||||
|
@ -422,6 +336,13 @@ redirect('/uploaduseravatar', '/api/avatars/upload');
|
||||||
redirect('/deletequickreply', '/api/quick-replies/delete');
|
redirect('/deletequickreply', '/api/quick-replies/delete');
|
||||||
redirect('/savequickreply', '/api/quick-replies/save');
|
redirect('/savequickreply', '/api/quick-replies/save');
|
||||||
|
|
||||||
|
// Redirect deprecated image endpoints
|
||||||
|
redirect('/uploadimage', '/api/images/upload');
|
||||||
|
redirect('/listimgfiles/:folder', '/api/images/list/:folder');
|
||||||
|
|
||||||
|
// Image management
|
||||||
|
app.use('/api/images', require('./src/endpoints/images').router);
|
||||||
|
|
||||||
// Quick reply management
|
// Quick reply management
|
||||||
app.use('/api/quick-replies', require('./src/endpoints/quick-replies').router);
|
app.use('/api/quick-replies', require('./src/endpoints/quick-replies').router);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const express = require('express');
|
||||||
|
const sanitize = require('sanitize-filename');
|
||||||
|
|
||||||
|
const { jsonParser } = require('../express-common');
|
||||||
|
const { DIRECTORIES } = require('../constants');
|
||||||
|
const { clientRelativePath, removeFileExtension, getImages } = require('../util');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure the directory for the provided file path exists.
|
||||||
|
* If not, it will recursively create the directory.
|
||||||
|
*
|
||||||
|
* @param {string} filePath - The full path of the file for which the directory should be ensured.
|
||||||
|
*/
|
||||||
|
function ensureDirectoryExistence(filePath) {
|
||||||
|
const dirname = path.dirname(filePath);
|
||||||
|
if (fs.existsSync(dirname)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ensureDirectoryExistence(dirname);
|
||||||
|
fs.mkdirSync(dirname);
|
||||||
|
}
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Endpoint to handle image uploads.
|
||||||
|
* The image should be provided in the request body in base64 format.
|
||||||
|
* Optionally, a character name can be provided to save the image in a sub-folder.
|
||||||
|
*
|
||||||
|
* @route POST /api/images/upload
|
||||||
|
* @param {Object} request.body - The request payload.
|
||||||
|
* @param {string} request.body.image - The base64 encoded image data.
|
||||||
|
* @param {string} [request.body.ch_name] - Optional character name to determine the sub-directory.
|
||||||
|
* @returns {Object} response - The response object containing the path where the image was saved.
|
||||||
|
*/
|
||||||
|
router.post('/upload', jsonParser, async (request, response) => {
|
||||||
|
// Check for image data
|
||||||
|
if (!request.body || !request.body.image) {
|
||||||
|
return response.status(400).send({ error: 'No image data provided' });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Extracting the base64 data and the image format
|
||||||
|
const splitParts = request.body.image.split(',');
|
||||||
|
const format = splitParts[0].split(';')[0].split('/')[1];
|
||||||
|
const base64Data = splitParts[1];
|
||||||
|
const validFormat = ['png', 'jpg', 'webp', 'jpeg', 'gif'].includes(format);
|
||||||
|
if (!validFormat) {
|
||||||
|
return response.status(400).send({ error: 'Invalid image format' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructing filename and path
|
||||||
|
let filename;
|
||||||
|
if (request.body.filename) {
|
||||||
|
filename = `${removeFileExtension(request.body.filename)}.${format}`;
|
||||||
|
} else {
|
||||||
|
filename = `${Date.now()}.${format}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if character is defined, save to a sub folder for that character
|
||||||
|
let pathToNewFile = path.join(DIRECTORIES.userImages, sanitize(filename));
|
||||||
|
if (request.body.ch_name) {
|
||||||
|
pathToNewFile = path.join(DIRECTORIES.userImages, sanitize(request.body.ch_name), sanitize(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureDirectoryExistence(pathToNewFile);
|
||||||
|
const imageBuffer = Buffer.from(base64Data, 'base64');
|
||||||
|
await fs.promises.writeFile(pathToNewFile, imageBuffer);
|
||||||
|
response.send({ path: clientRelativePath(pathToNewFile) });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
response.status(500).send({ error: 'Failed to save the image' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/list/:folder', (req, res) => {
|
||||||
|
const directoryPath = path.join(process.cwd(), DIRECTORIES.userImages, sanitize(req.params.folder));
|
||||||
|
|
||||||
|
if (!fs.existsSync(directoryPath)) {
|
||||||
|
fs.mkdirSync(directoryPath, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const images = getImages(directoryPath);
|
||||||
|
return res.send(images);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return res.status(500).send({ error: 'Unable to retrieve files' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = { router };
|
Loading…
Reference in New Issue