mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Export chats as .txt files
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -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/
|
||||
|
@ -2363,6 +2363,7 @@
|
||||
</div>
|
||||
<div class="flex-container height100pSpaceEvenly">
|
||||
<div class="renameChatButton fa-solid fa-pen"></div>
|
||||
<div class="exportChatButton fa-solid fa-file-export"></div>
|
||||
<div file_name="" class="PastChat_cross fa-solid fa-circle-xmark"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -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();
|
||||
|
@ -2618,7 +2618,8 @@ h5 {
|
||||
flex: 1
|
||||
}
|
||||
|
||||
.renameChatButton {
|
||||
.renameChatButton,
|
||||
.exportChatButton {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
57
server.js
57
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);
|
||||
|
Reference in New Issue
Block a user