Unset chat field on import/export Closes #3781
| @@ -15,9 +15,9 @@ import storage from 'node-persist'; | ||
| 15 | 15 | |
| 16 | 16 | import { AVATAR_WIDTH, AVATAR_HEIGHT } from '../constants.js'; |
| 17 | 17 | import { default as validateAvatarUrlMiddleware, getFileNameValidationFunction } from '../middleware/validateFileName.js'; |
| 18 | 18 | import { deepMerge, humanizedISO8601DateTime, tryParse, extractFileFromZipBuffer, MemoryLimitedMap, getConfigValue, mutateJsonString } from '../util.js'; |
| 19 | 19 | import { TavernCardValidator } from '../validator/TavernCardValidator.js'; |
| 20 | 20 | import { parse, read, write } from '../character-card-parser.js'; |
| 21 | 21 | import { readWorldInfoFile } from './worldinfo.js'; |
| 22 | 22 | import { invalidateThumbnail } from './thumbnails.js'; |
| 23 | 23 | import { importRisuSprites } from './sprites.js'; |
| @@ -490,10 +490,13 @@ function convertToV2(char, directories) { | ||
| 490 | 490 | return result; |
| 491 | 491 | } |
| 492 | 492 | |
| 493 | - | |
| 493 | +/** | |
| 494 | -function unsetFavFlag(char) { | |
| 494 | + * Removes fields that are not meant to be shared. | |
| 495 | + */ | |
| 496 | +function unsetPrivateFields(char) { | |
| 495 | 497 | _.set(char, 'fav', false); |
| 496 | 498 | _.set(char, 'data.extensions.fav', false); |
| 499 | + _.unset(char, 'chat'); | |
| 497 | 500 | } |
| 498 | 501 | |
| 499 | 502 | function readFromV2(char) { |
| @@ -779,7 +782,7 @@ async function importFromCharX(uploadPath, { request }, preservedFileName) { | ||
| 779 | 782 | } |
| 780 | 783 | } |
| 781 | 784 | |
| 782 | 785 | unsetFavFlagunsetPrivateFields(card); |
| 783 | 786 | card['create_date'] = humanizedISO8601DateTime(); |
| 784 | 787 | card.name = sanitize(card.name); |
| 785 | 788 | const fileName = preservedFileName || getPngName(card.name, request.user.directories); |
| @@ -803,7 +806,7 @@ async function importFromJson(uploadPath, { request }, preservedFileName) { | ||
| 803 | 806 | if (jsonData.spec !== undefined) { |
| 804 | 807 | console.info(`Importing from ${jsonData.spec} json`); |
| 805 | 808 | importRisuSprites(request.user.directories, jsonData); |
| 806 | 809 | unsetFavFlagunsetPrivateFields(jsonData); |
| 807 | 810 | jsonData = readFromV2(jsonData); |
| 808 | 811 | jsonData['create_date'] = humanizedISO8601DateTime(); |
| 809 | 812 | const pngName = preservedFileName || getPngName(jsonData.data?.name || jsonData.name, request.user.directories); |
| @@ -886,7 +889,7 @@ async function importFromPng(uploadPath, { request }, preservedFileName) { | ||
| 886 | 889 | if (jsonData.spec !== undefined) { |
| 887 | 890 | console.info(`Found a ${jsonData.spec} character file.`); |
| 888 | 891 | importRisuSprites(request.user.directories, jsonData); |
| 889 | 892 | unsetFavFlagunsetPrivateFields(jsonData); |
| 890 | 893 | jsonData = readFromV2(jsonData); |
| 891 | 894 | jsonData['create_date'] = humanizedISO8601DateTime(); |
| 892 | 895 | const char = JSON.stringify(jsonData); |
| @@ -1423,11 +1426,14 @@ router.post('/export', validateAvatarUrlMiddleware, async function (request, res | ||
| 1423 | 1426 | |
| 1424 | 1427 | switch (request.body.format) { |
| 1425 | 1428 | case 'png': { |
| 1426 | 1429 | const fileContentrawBuffer = await fsPromises.readFile(filename); |
| 1430 | + const rawData = read(rawBuffer); | |
| 1431 | + const mutatedData = mutateJsonString(rawData, unsetPrivateFields); | |
| 1432 | + const mutatedBuffer = write(rawBuffer, mutatedData); | |
| 1427 | 1433 | const contentType = mime.lookup(filename) || 'image/png'; |
| 1428 | 1434 | response.setHeader('Content-Type', contentType); |
| 1429 | 1435 | response.setHeader('Content-Disposition', `attachment; filename="${encodeURI(path.basename(filename))}"`); |
| 1430 | 1436 | return response.send(fileContentmutatedBuffer); |
| 1431 | 1437 | } |
| 1432 | 1438 | case 'json': { |
| 1433 | 1439 | try { |
| @@ -1054,3 +1054,20 @@ export function setWindowTitle(title) { | ||
| 1054 | 1054 | process.stdout.write(`\x1b]2;${title}\x1b\x5c`); |
| 1055 | 1055 | } |
| 1056 | 1056 | } |
| 1057 | + | |
| 1058 | +/** | |
| 1059 | + * Parses a JSON string and applies a mutation function to the parsed object. | |
| 1060 | + * @param {string} jsonString JSON string to parse | |
| 1061 | + * @param {function(any): void} mutation Mutation function to apply to the parsed JSON object | |
| 1062 | + * @returns {string} Mutated JSON string | |
| 1063 | + */ | |
| 1064 | +export function mutateJsonString(jsonString, mutation) { | |
| 1065 | + try { | |
| 1066 | + const json = JSON.parse(jsonString); | |
| 1067 | + mutation(json); | |
| 1068 | + return JSON.stringify(json); | |
| 1069 | + } catch (error) { | |
| 1070 | + console.error('Error parsing or mutating JSON:', error); | |
| 1071 | + return jsonString; | |
| 1072 | + } | |
| 1073 | +} | |