diff --git a/.gitignore b/.gitignore index 531d61538..9e40fb900 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ public/characters/ public/User Avatars/ public/backgrounds/ public/groups/ +public/group chats/ public/worlds/ public/css/bg_load.css public/themes/ diff --git a/public/index.html b/public/index.html index 0c93297e7..99ca6fcf2 100644 --- a/public/index.html +++ b/public/index.html @@ -2363,6 +2363,7 @@
+
@@ -2713,4 +2714,4 @@ - + \ No newline at end of file diff --git a/public/script.js b/public/script.js index 5c3c6249d..8ca43ef4f 100644 --- a/public/script.js +++ b/public/script.js @@ -5795,6 +5795,43 @@ $(document).ready(function () { } }); + $(document).on("click", ".exportChatButton", async function () { + const filenamefull = $(this).closest('.select_chat_block_wrapper').find('.select_chat_block_filename').text(); + const filename = filenamefull.replace('.jsonl', ''); + const body = { + is_group: !!selected_group, + avatar_url: characters[this_chid]?.avatar, + file: `${filename}.jsonl`, + exportfilename: `${filename}.txt`, + } + console.log(body); + try { + const response = await fetch('/exportchat', { + method: 'POST', + body: JSON.stringify(body), + headers: getRequestHeaders(), + }); + const data = await response.json(); + if (!response.ok) { + // display error message + console.log(data.message); + await delay(250); + toastr.error(`Error: ${data.message}`); + return; + } else { + // success, handle response data + console.log(data); + await delay(250); + toastr.success(data.message); + } + } catch (error) { + // display error message + console.log(`An error has occurred: ${error.message}`); + await delay(250); + toastr.error(`Error: ${error.message}`); + } + }); + $("#talkativeness_slider").on("input", function () { if (menu_type == "create") { create_save_talkativeness = $("#talkativeness_slider").val(); diff --git a/public/style.css b/public/style.css index 599e7caa8..9d737c7e7 100644 --- a/public/style.css +++ b/public/style.css @@ -2618,7 +2618,8 @@ h5 { flex: 1 } -.renameChatButton { +.renameChatButton, +.exportChatButton { cursor: pointer; } @@ -4467,4 +4468,4 @@ body.waifuMode #avatar_zoom_popup { overflow-y: auto; overflow-x: hidden; } -} +} \ No newline at end of file diff --git a/server.js b/server.js index fb48eb6d4..5604e40f3 100644 --- a/server.js +++ b/server.js @@ -1593,6 +1593,63 @@ app.post("/dupecharacter", jsonParser, async function (request, response) { } }); +app.post("/exportchat", jsonParser, async function (request, response) { + if (!request.body.file || (!request.body.avatar_url && request.body.is_group === false)) { + return response.sendStatus(400); + } + const pathToFolder = request.body.is_group + ? directories.groupChats + : path.join(directories.chats, String(request.body.avatar_url).replace('.png', '')); + //let charname = String(sanitize(request.body.avatar_url)).replace('.png', ''); + let filename = path.join(pathToFolder, request.body.file); + let exportfilename = path.join(pathToFolder, request.body.exportfilename) + if (!fs.existsSync(filename)) { + const errorMessage = { + message: `Could not find JSONL file to export. Source chat file: ${filename}. Intended destination file: ${exportfilename}.` + } + console.log(errorMessage.message); + return response.status(404).json(errorMessage); + } + if (fs.existsSync(exportfilename)) { + const errorMessage = { + message: `File by that name already exists. Export chat aborted.` + } + console.log(errorMessage.message); + return response.status(400).json(errorMessage); + } + try { + const readline = require('readline'); + const fs = require('fs'); + const readStream = fs.createReadStream(filename); + const writeStream = fs.createWriteStream(exportfilename); + const rl = readline.createInterface({ + input: readStream, + }); + rl.on('line', (line) => { + const data = JSON.parse(line); + if (data.mes) { + const name = data.name; + const message = data.mes.replace(/\r?\n/g, '\n'); + writeStream.write(`${name}: ${message}\n\n`); + } + }); + rl.on('close', () => { + writeStream.end(); + }); + //fs.promises.copyFile(filename, exportfilename) + const successMessage = { + message: `Chat exported as ${exportfilename}` + } + console.log(`Chat exported as ${exportfilename}`); + return response.status(200).json(successMessage); + } + catch (err) { + console.log("chat export failed.") + console.log(err); + return response.sendStatus(400); + } +}) + app.post("/exportcharacter", jsonParser, async function (request, response) { if (!request.body.format || !request.body.avatar_url) { return response.sendStatus(400);