From 1315f0968bbc94aec0b6c3d1d0392cae00130784 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Mon, 1 Jul 2024 21:48:56 +0300 Subject: [PATCH] Support all file formats for replace/update --- public/index.html | 2 +- public/script.js | 19 +++++++++++-------- src/endpoints/characters.js | 27 +++++++++++++++++---------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/public/index.html b/public/index.html index b3a17b8c3..61ce9e14d 100644 --- a/public/index.html +++ b/public/index.html @@ -4796,7 +4796,7 @@ - +
diff --git a/public/script.js b/public/script.js index cca7407e7..655feb483 100644 --- a/public/script.js +++ b/public/script.js @@ -8449,10 +8449,10 @@ async function connectAPISlash(_, text) { /** * Imports supported files dropped into the app window. * @param {File[]} files Array of files to process - * @param {boolean?} preserveFileNames Whether to preserve original file names + * @param {Map} [data] Extra data to pass to the import function * @returns {Promise} */ -export async function processDroppedFiles(files, preserveFileNames = false) { +export async function processDroppedFiles(files, data = new Map()) { const allowedMimeTypes = [ 'application/json', 'image/png', @@ -8469,7 +8469,8 @@ export async function processDroppedFiles(files, preserveFileNames = false) { for (const file of files) { const extension = file.name.split('.').pop().toLowerCase(); if (allowedMimeTypes.includes(file.type) || allowedExtensions.includes(extension)) { - await importCharacter(file, preserveFileNames); + const preservedName = data instanceof Map && data.get(file); + await importCharacter(file, preservedName); } else { toastr.warning('Unsupported file type: ' + file.name); } @@ -8479,10 +8480,10 @@ export async function processDroppedFiles(files, preserveFileNames = false) { /** * Imports a character from a file. * @param {File} file File to import - * @param {boolean?} preserveFileName Whether to preserve original file name + * @param {string?} preserveFileName Whether to preserve original file name * @returns {Promise} */ -async function importCharacter(file, preserveFileName = false) { +async function importCharacter(file, preserveFileName = '') { if (is_group_generating || is_send_press) { toastr.error('Cannot import characters while generating. Stop the request and try again.', 'Import aborted'); throw new Error('Cannot import character while generating'); @@ -8498,7 +8499,7 @@ async function importCharacter(file, preserveFileName = false) { const formData = new FormData(); formData.append('avatar', file); formData.append('file_type', format); - formData.append('preserve_file_name', String(preserveFileName)); + if (preserveFileName) formData.append('preserved_name', preserveFileName); const data = await jQuery.ajax({ type: 'POST', @@ -10637,10 +10638,12 @@ jQuery(async function () { } try { - const cloneFile = new File([file], characters[this_chid].avatar, { type: file.type }); const chatFile = characters[this_chid]['chat']; - await processDroppedFiles([cloneFile], true); + const data = new Map(); + data.set(file, characters[this_chid].avatar); + await processDroppedFiles([file], data); await openCharacterChat(chatFile); + await fetch(getThumbnailUrl('avatar', characters[this_chid].avatar), { cache: 'no-cache' }); } catch { toastr.error('Failed to replace the character card.', 'Something went wrong'); } diff --git a/src/endpoints/characters.js b/src/endpoints/characters.js index 6d60bdbb0..e4f43367b 100644 --- a/src/endpoints/characters.js +++ b/src/endpoints/characters.js @@ -499,15 +499,16 @@ function convertWorldInfoToCharacterBook(name, entries) { * Import a character from a YAML file. * @param {string} uploadPath Path to the uploaded file * @param {{ request: import('express').Request, response: import('express').Response }} context Express request and response objects + * @param {string|undefined} preservedFileName Preserved file name * @returns {Promise} Internal name of the character */ -async function importFromYaml(uploadPath, context) { +async function importFromYaml(uploadPath, context, preservedFileName) { const fileText = fs.readFileSync(uploadPath, 'utf8'); fs.rmSync(uploadPath); const yamlData = yaml.parse(fileText); console.log('Importing from YAML'); yamlData.name = sanitize(yamlData.name); - const fileName = getPngName(yamlData.name, context.request.user.directories); + const fileName = preservedFileName || getPngName(yamlData.name, context.request.user.directories); let char = convertToV2({ 'name': yamlData.name, 'description': yamlData.context ?? '', @@ -532,9 +533,10 @@ async function importFromYaml(uploadPath, context) { * @param {string} uploadPath * @param {object} params * @param {import('express').Request} params.request + * @param {string|undefined} preservedFileName Preserved file name * @returns {Promise} Internal name of the character */ -async function importFromCharX(uploadPath, { request }) { +async function importFromCharX(uploadPath, { request }, preservedFileName) { const data = fs.readFileSync(uploadPath); fs.rmSync(uploadPath); console.log('Importing from CharX'); @@ -567,7 +569,7 @@ async function importFromCharX(uploadPath, { request }) { unsetFavFlag(card); card['create_date'] = humanizedISO8601DateTime(); card.name = sanitize(card.name); - const fileName = getPngName(card.name, request.user.directories); + const fileName = preservedFileName || getPngName(card.name, request.user.directories); const result = await writeCharacterData(avatar, JSON.stringify(card), fileName, request); return result ? fileName : ''; } @@ -576,9 +578,10 @@ async function importFromCharX(uploadPath, { request }) { * Import a character from a JSON file. * @param {string} uploadPath Path to the uploaded file * @param {{ request: import('express').Request, response: import('express').Response }} context Express request and response objects + * @param {string|undefined} preservedFileName Preserved file name * @returns {Promise} Internal name of the character */ -async function importFromJson(uploadPath, { request }) { +async function importFromJson(uploadPath, { request }, preservedFileName) { const data = fs.readFileSync(uploadPath, 'utf8'); fs.unlinkSync(uploadPath); @@ -590,7 +593,7 @@ async function importFromJson(uploadPath, { request }) { unsetFavFlag(jsonData); jsonData = readFromV2(jsonData); jsonData['create_date'] = humanizedISO8601DateTime(); - const pngName = getPngName(jsonData.data?.name || jsonData.name, request.user.directories); + const pngName = preservedFileName || getPngName(jsonData.data?.name || jsonData.name, request.user.directories); const char = JSON.stringify(jsonData); const result = await writeCharacterData(defaultAvatarPath, char, pngName, request); return result ? pngName : ''; @@ -600,7 +603,7 @@ async function importFromJson(uploadPath, { request }) { if (jsonData.creator_notes) { jsonData.creator_notes = jsonData.creator_notes.replace('Creator\'s notes go here.', ''); } - const pngName = getPngName(jsonData.name, request.user.directories); + const pngName = preservedFileName || getPngName(jsonData.name, request.user.directories); let char = { 'name': jsonData.name, 'description': jsonData.description ?? '', @@ -626,7 +629,7 @@ async function importFromJson(uploadPath, { request }) { if (jsonData.creator_notes) { jsonData.creator_notes = jsonData.creator_notes.replace('Creator\'s notes go here.', ''); } - const pngName = getPngName(jsonData.char_name, request.user.directories); + const pngName = preservedFileName || getPngName(jsonData.char_name, request.user.directories); let char = { 'name': jsonData.char_name, 'description': jsonData.char_persona ?? '', @@ -1089,8 +1092,8 @@ function getPngName(file, directories) { * @returns {string | undefined} - The preserved name if the request is valid, otherwise undefined */ function getPreservedName(request) { - return request.body.file_type === 'png' && request.body.preserve_file_name === 'true' && request.file?.originalname - ? path.parse(request.file.originalname).name + return typeof request.body.preserved_name === 'string' && request.body.preserved_name.length > 0 + ? path.parse(request.body.preserved_name).name : undefined; } @@ -1123,6 +1126,10 @@ router.post('/import', urlencodedParser, async function (request, response) { return response.sendStatus(400); } + if (preservedFileName) { + invalidateThumbnail(request.user.directories, 'avatar', `${preservedFileName}.png`); + } + response.send({ file_name: fileName }); } catch (err) { console.log(err);