diff --git a/public/script.js b/public/script.js index 842746dcf..e189331de 100644 --- a/public/script.js +++ b/public/script.js @@ -49,6 +49,7 @@ import { editGroup, deleteGroupChat, renameGroupChat, + importGroupChat, } from "./scripts/group-chats.js"; import { @@ -3409,6 +3410,7 @@ async function read_avatar_load(input) { await delay(durationSaveEdit); await fetch(getThumbnailUrl('avatar', formData.get('avatar_url')), { method: 'GET', + cache: 'no-cache', headers: { 'pragma': 'no-cache', 'cache-control': 'no-cache', @@ -3973,7 +3975,7 @@ async function getPastCharacterChats() { return data; } -async function displayPastChats() { +export async function displayPastChats() { $("#select_chat_div").empty(); const group = selected_group ? groups.find(x => x.id === selected_group) : null; @@ -4010,7 +4012,7 @@ async function displayPastChats() { $("#select_chat_div").append(template); - if (currentChat === fileName.replace(".jsonl", "")) { + if (currentChat === fileName.toString().replace(".jsonl", "")) { $("#select_chat_div").find(".select_chat_block:last").attr("highlight", true); } } @@ -4055,7 +4057,6 @@ async function getStatusNovel() { } } - function selectRightMenuWithAnimation(selectedMenuId) { const displayModes = { 'rm_info_block': 'flex', @@ -4076,13 +4077,7 @@ function selectRightMenuWithAnimation(selectedMenuId) { easing: animation_easing, complete: function () { }, }); - - - - // $(menu).find('#groupCurrentMemberListToggle').click(); - } - }) } @@ -4124,10 +4119,8 @@ function select_rm_info(type, charId) { setTimeout(function () { $(`#rm_characters_block [title="${charId + '.png'}"]`).parent().removeClass('flash animated'); }, 5000); - } - setRightTabSelectedClass(); prev_selected_char = charId; @@ -4457,6 +4450,27 @@ export async function saveChatConditional() { } } +async function importCharacterChat(formData) { + await jQuery.ajax({ + type: "POST", + url: "/importchat", + data: formData, + beforeSend: function () { + }, + cache: false, + contentType: false, + processData: false, + success: async function (data) { + if (data.res) { + await displayPastChats(); + } + }, + error: function () { + $("#create_button").removeAttr("disabled"); + }, + }); +} + function updateViewMessageIds() { $('#chat').find(".mes").each(function (index, element) { $(element).attr("mesid", index); @@ -6289,12 +6303,13 @@ $(document).ready(function () { $("#chat_import_file").click(); }); - $("#chat_import_file").on("change", function (e) { + $("#chat_import_file").on("change", async function (e) { var file = e.target.files[0]; - //console.log(1); + if (!file) { return; } + var ext = file.name.match(/\.(\w+)$/); if ( !ext || @@ -6303,33 +6318,23 @@ $(document).ready(function () { return; } + if (selected_group && file.name.endsWith('.json')) { + toastr.warning("Only SillyTavern's own format is supported for group chat imports. Sorry!"); + return; + } + var format = ext[1].toLowerCase(); $("#chat_import_file_type").val(format); - //console.log(format); + var formData = new FormData($("#form_import_chat").get(0)); - //console.log('/importchat entered with: '+formData); - jQuery.ajax({ - type: "POST", - url: "/importchat", - data: formData, - beforeSend: function () { - $("#select_chat_div").html(""); - $("#load_select_chat_div").css("display", "block"); - //$('#create_button').attr('value','Creating...'); - }, - cache: false, - contentType: false, - processData: false, - success: function (data) { - //console.log(data); - if (data.res) { - displayPastChats(); - } - }, - error: function (jqXHR, exception) { - $("#create_button").removeAttr("disabled"); - }, - }); + $("#select_chat_div").html(""); + $("#load_select_chat_div").css("display", "block"); + + if (selected_group) { + await importGroupChat(formData); + } else { + await importCharacterChat(formData); + } }); $("#rm_button_group_chats").click(function () { diff --git a/public/scripts/group-chats.js b/public/scripts/group-chats.js index 171908216..65f33cc14 100644 --- a/public/scripts/group-chats.js +++ b/public/scripts/group-chats.js @@ -47,6 +47,7 @@ import { select_selected_character, cancelTtsPlay, isMultigenEnabled, + displayPastChats, } from "../script.js"; import { appendTagToList, createTagMapFromList, getTagsList, applyTagsOnCharacterSelect } from './tags.js'; @@ -292,6 +293,12 @@ async function getGroups() { if (group.past_metadata == undefined) { group.past_metadata = {}; } + if (typeof group.chat_id === 'number') { + group.chat_id = String(group.chat_id); + } + if (Array.isArray(group.chats) && group.chats.some(x => typeof x === 'number')) { + group.chats = group.chats.map(x => String(x)); + } } } } @@ -1282,6 +1289,34 @@ export async function deleteGroupChat(groupId, chatId) { } } +export async function importGroupChat(formData) { + await jQuery.ajax({ + type: "POST", + url: "/importgroupchat", + data: formData, + beforeSend: function () { + }, + cache: false, + contentType: false, + processData: false, + success: async function (data) { + if (data.res) { + const chatId = data.res; + const group = groups.find(x => x.id == selected_group); + + if (group) { + group.chats.push(chatId); + await editGroup(selected_group, true, true); + await displayPastChats(); + } + } + }, + error: function () { + $("#create_button").removeAttr("disabled"); + }, + }); +} + export async function saveGroupBookmarkChat(groupId, name, metadata) { const group = groups.find(x => x.id === groupId); diff --git a/server.js b/server.js index 03e80abcd..062cd7084 100644 --- a/server.js +++ b/server.js @@ -1754,6 +1754,17 @@ app.post("/exportcharacter", jsonParser, async function (request, response) { return response.sendStatus(400); }); +app.post("/importgroupchat", urlencodedParser, function (request, response) { + try { + const filedata = request.file; + const chatname = humanizedISO8601DateTime(); + fs.copyFileSync(`./uploads/${filedata.filename}`, (`${directories.groupChats}/${chatname}.jsonl`)); + return response.send({ res: chatname }); + } catch (error) { + console.error(error); + return response.send({ error: true }); + } +}); app.post("/importchat", urlencodedParser, function (request, response) { if (!request.body) return response.sendStatus(400); @@ -1763,9 +1774,8 @@ app.post("/importchat", urlencodedParser, function (request, response) { let avatar_url = (request.body.avatar_url).replace('.png', ''); let ch_name = request.body.character_name; if (filedata) { - if (format === 'json') { - fs.readFile('./uploads/' + filedata.filename, 'utf8', (err, data) => { + fs.readFile(`./uploads/${filedata.filename}`, 'utf8', (err, data) => { if (err) { console.log(err); @@ -1782,7 +1792,6 @@ app.post("/importchat", urlencodedParser, function (request, response) { user_name: 'You', character_name: ch_name, create_date: humanizedISO8601DateTime(), - }, ...history.msgs.map( (message) => ({ @@ -1803,7 +1812,7 @@ app.post("/importchat", urlencodedParser, function (request, response) { const errors = []; newChats.forEach(chat => fs.writeFile( - chatsPath + avatar_url + '/' + ch_name + ' - ' + humanizedISO8601DateTime() + ' imported.jsonl', + `${chatsPath + avatar_url}/${ch_name} - ${humanizedISO8601DateTime()} imported.jsonl`, chat.map(JSON.stringify).join('\n'), 'utf8', (err) => err ?? errors.push(err) @@ -1832,8 +1841,7 @@ app.post("/importchat", urlencodedParser, function (request, response) { let jsonData = json5.parse(line); if (jsonData.user_name !== undefined || jsonData.name !== undefined) { - //console.log(humanizedISO8601DateTime()+':/importchat copying chat as '+ch_name+' - '+humanizedISO8601DateTime()+'.jsonl'); - fs.copyFile('./uploads/' + filedata.filename, chatsPath + avatar_url + '/' + ch_name + ' - ' + humanizedISO8601DateTime() + '.jsonl', (err) => { //added character name and replaced Date.now() with humanizedISO8601DateTime + fs.copyFile(`./uploads/${filedata.filename}`, (`${chatsPath + avatar_url}/${ch_name} - ${humanizedISO8601DateTime()}.jsonl`), (err) => { if (err) { response.send({ error: true }); return console.log(err); @@ -1849,9 +1857,7 @@ app.post("/importchat", urlencodedParser, function (request, response) { rl.close(); }); } - } - }); app.post('/importworldinfo', urlencodedParser, (request, response) => {