diff --git a/public/index.html b/public/index.html index 5113bd73a..ddf0e88a7 100644 --- a/public/index.html +++ b/public/index.html @@ -1415,6 +1415,7 @@
" + p1.replace(/\"/g, "") + ""; - } else { - return match; - } - }); + mes = mes.replace(/```[\s\S]*?```|``[\s\S]*?``|`[\s\S]*?`|(\".+?\")/gm, function (match, p1) { + if (p1) { + return "
" + p1.replace(/\"/g, "") + ""; + } else { + return match; + } + }); mes = converter.makeHtml(mes); //mes = mes.replace(/{.*}/g, ""); mes = mes.replace(/{{(\*?.+?\*?)}}/g, ""); @@ -2008,7 +2008,7 @@ async function Generate(type, automatic_trigger, force_name2) { url: generate_url, // data: JSON.stringify(generate_data), beforeSend: function () { - //$('#create_button').attr('value','Creating...'); + }, cache: false, dataType: "json", @@ -2427,7 +2427,7 @@ async function saveChat(chat_name, withMetadata) { avatar_url: characters[this_chid].avatar, }), beforeSend: function () { - //$('#create_button').attr('value','Creating...'); + }, cache: false, dataType: "json", @@ -3020,7 +3020,7 @@ async function getAllCharaChats() { url: "/getallchatsofcharacter", data: JSON.stringify({ avatar_url: characters[this_chid].avatar }), beforeSend: function () { - //$('#create_button').attr('value','Creating...'); + }, cache: false, dataType: "json", @@ -3086,7 +3086,7 @@ async function getStatusNovel() { url: "/getstatus_novelai", // data: JSON.stringify(data), beforeSend: function () { - //$('#create_button').attr('value','Creating...'); + }, cache: false, dataType: "json", @@ -3177,7 +3177,7 @@ function select_selected_character(chid) { $("#rm_button_back").css("display", "none"); //$("#character_import_button").css("display", "none"); $("#create_button").attr("value", "Save"); // what is the use case for this? - $("#create_button_label").css("display", "none"); + //$("#create_button_label").css("display", "none"); $("#rm_button_selected_ch").children("h2").text(display_name); $("#add_avatar_button").val(""); @@ -3206,7 +3206,9 @@ function select_selected_character(chid) { updateFavButtonState(characters[chid].fav == "true"); $("#avatar_load_preview").attr("src", this_avatar); - $("#name_div").css("display", "none"); + $("#name_div").removeClass('displayBlock'); + $("#name_div").addClass('displayNone'); + $("#renameCharButton").css("display", "block"); $("#form_create").attr("actiontype", "editcharacter"); active_character = chid; @@ -3254,7 +3256,9 @@ function select_rm_create() { } $("#avatar_div").css("display", "flex"); $("#avatar_load_preview").attr("src", default_avatar); - $("#name_div").css("display", "block"); + $("#renameCharButton").css('display', 'none'); + $("#name_div").removeClass('displayNone'); + $("#name_div").addClass('displayBlock'); $("#form_create").attr("actiontype", "createcharacter"); } @@ -4264,13 +4268,19 @@ $(document).ready(function () { url: "/editcharacter", data: formData, beforeSend: function () { - $("#create_button").attr("disabled", true); + //$("#create_button").attr("disabled", true); $("#create_button").attr("value", "Save"); }, cache: false, contentType: false, processData: false, success: function (html) { + + //currently this updates the displayed H2 name regardless of soft errors, doesn't detect actual errors. + let h2text = $("#character_name_pole").val(); + console.log('about to change name! in h2'); + $("#rm_button_selected_ch").children("h2").text(h2text); + $(".mes").each(function () { if ($(this).attr("is_system") == 'true') { return; @@ -4320,6 +4330,8 @@ $(document).ready(function () { error: function (jqXHR, exception) { $("#create_button").removeAttr("disabled"); $("#result_info").html("Error: no connection"); + console.log('Cant use that name! Invalid or already exists.'); + alert('Cant use that name! Invalid or already exists.'); }, }); } @@ -4366,6 +4378,10 @@ $(document).ready(function () { } }); + $("#renameCharButton").on('click', function () { + $("#name_div").toggleClass('displayNone displayBlock'); + }) + $("#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 2db6dc0c1..843bdc997 100644 --- a/public/style.css +++ b/public/style.css @@ -925,6 +925,14 @@ select option:not(:checked) { color: #ffff00 !important; } +.displayBlock { + display: block !important; +} + +.displayNone { + display: none !important; +} + #api_url_text, #textgenerationwebui_api_url_text { /*margin-right: 4px;*/ diff --git a/server.js b/server.js index e4df33dd0..1afe69866 100644 --- a/server.js +++ b/server.js @@ -277,10 +277,10 @@ app.get("/", function (request, response) { app.get("/notes/*", function (request, response) { response.sendFile(__dirname + "/public" + request.url + ".html"); }); -app.get('/get_faq', function(_, response) { +app.get('/get_faq', function (_, response) { response.sendFile(__dirname + "/faq.md"); }); -app.get('/get_readme', function(_, response) { +app.get('/get_readme', function (_, response) { response.sendFile(__dirname + "/readme.md"); }); @@ -385,7 +385,7 @@ app.post("/generate_textgenerationwebui", jsonParser, async function (request, r async function* readWebsocket() { const streamingUrl = request.header('X-Streaming-URL'); - const websocket = new WebSocket(streamingUrl); + const websocket = new WebSocket(streamingUrl); websocket.on('open', async function () { console.log('websocket open'); @@ -633,7 +633,7 @@ function checkServer() { //***************** Main functions function charaFormatData(data) { - var char = { "name": data.ch_name, "description": data.description, "personality": data.personality, "first_mes": data.first_mes, "avatar": 'none', "chat": data.ch_name + ' - ' + humanizedISO8601DateTime(), "mes_example": data.mes_example, "scenario": data.scenario, "create_date": humanizedISO8601DateTime(), "talkativeness": data.talkativeness, "fav": data.fav}; + var char = { "name": data.ch_name, "description": data.description, "personality": data.personality, "first_mes": data.first_mes, "avatar": 'none', "chat": data.ch_name + ' - ' + humanizedISO8601DateTime(), "mes_example": data.mes_example, "scenario": data.scenario, "create_date": humanizedISO8601DateTime(), "talkativeness": data.talkativeness, "fav": data.fav }; return char; } app.post("/createcharacter", urlencodedParser, function (request, response) { @@ -677,22 +677,87 @@ app.post("/createcharacter", urlencodedParser, function (request, response) { app.post("/editcharacter", urlencodedParser, async function (request, response) { - if (!request.body) return response.sendStatus(400); + + if (!request.body) { + console.error('Error: no response body detected'); + response.send('Error: no response body detected'); + return; + // return response.sendStatus(400); + } + + if (request.body.ch_name === '' || request.body.ch_name === undefined || request.body.ch_name === '.') { + console.error('Error: invalid name.'); + response.send('Error: invalid name.'); + return; + } let filedata = request.file; //console.log(filedata.mimetype); var fileType = ".png"; var img_file = "ai"; var img_path = charactersPath; - + var to_del_file = undefined; var char = charaFormatData(request.body);//{"name": request.body.ch_name, "description": request.body.description, "personality": request.body.personality, "first_mes": request.body.first_mes, "avatar": request.body.avatar_url, "chat": request.body.chat, "last_mes": request.body.last_mes, "mes_example": ''}; char.chat = request.body.chat; char.create_date = request.body.create_date; char = JSON.stringify(char); let target_img = (request.body.avatar_url).replace('.png', ''); + let potentialNewCharCardFile = directories.characters + sanitize(request.body.ch_name) + '.png'; + let potentialSpritesFolder = directories.characters + sanitize(target_img) + '/'; + let potentialChatsFolder = directories.chats + sanitize(target_img) + '/'; + let potentialNewName = request.body.ch_name; + //console.log('CurFile: ' + target_img); + //console.log('CurChatDir: ' + potentialChatsFolder); + //console.log('CurSpritesDir: ' + potentialSpritesFolder); + //console.log('NewFile: ' + potentialNewCharCardFile); + + //if name_div has been edited, that means the char is being renamed + if (potentialNewName !== undefined && potentialNewName !== '' && potentialNewName !== target_img) { + //console.log(potentialNewName + 'is valid and not same as ' + target_img + ', possible rename detected.'); + if (!fs.existsSync(potentialNewCharCardFile)) { + to_del_file = img_path + sanitize(target_img) + '.png'; + target_img = sanitize(request.body.ch_name); + //console.log(potentialNewCharCardFile + ' does not already exist, renaming greenlit.'); + var renameChatsFolderTo = directories.chats + sanitize(target_img) + "/"; + var renameSpritesFolderTo = directories.characters + sanitize(target_img) + "/"; + //console.log('NewFile: ' + target_img); + //console.log('NewChatsDir: ' + renameChatsFolderTo); + //console.log('NewSpritesDir: ' + renameSpritesFolderTo); + //console.log('DelFile: ' + to_del_file); + + } else { + console.error(potentialNewCharCardFile + " already existed, so you can't rename to that!"); + //this needs to send a response back to the HTML to give a visual warning + return; + } + } + try { if (!filedata) { + if (to_del_file !== undefined) { + if (!fs.existsSync(renameChatsFolderTo)) { + if (fs.existsSync(potentialChatsFolder)) { + fs.renameSync(potentialChatsFolder, renameChatsFolderTo); + console.log('RENAMED: Chats folder: ' + potentialChatsFolder + " >> " + renameChatsFolderTo); + } else { console.log("Info: No chat folder to rename."); } + } else { console.error('ERROR: same chat folder name already existed. Chats Folder rename aborted.'); } + + if (!fs.existsSync(renameSpritesFolderTo)) { + if (fs.existsSync(potentialSpritesFolder)) { + fs.renameSync(potentialSpritesFolder, renameSpritesFolderTo); + console.log('RENAMED: Sprites folder:' + potentialSpritesFolder + ' >> ' + renameSpritesFolderTo); + } else { console.log("Info: No sprites folder to rename."); } + } else { console.error('ERROR: same sprites folder name already existed. Sprites Folder rename aborted.'); } + + console.log('REPLACING: ' + to_del_file + ' with ' + directories.characters + target_img + '.png'); + await charaWrite(img_path + request.body.avatar_url, char, target_img, response, 'Character saved'); + + fs.rmSync(to_del_file); + to_del_file = undefined; + return; + } //else { console.log("No rename detected, updating current card only."); } await charaWrite(img_path + request.body.avatar_url, char, target_img, response, 'Character saved'); + } else { //console.log(filedata.filename); img_path = "uploads/"; @@ -704,8 +769,10 @@ app.post("/editcharacter", urlencodedParser, async function (request, response) } } catch { - return response.send(400); + //return response.send(400); + console.error('An error occured, character edit invalidated.'); } + }); app.post("/deletecharacter", urlencodedParser, function (request, response) { if (!request.body || !request.body.avatar_url) { @@ -2360,7 +2427,7 @@ const setupTasks = async function () { await spp.load(`./src/sentencepiece/tokenizer.model`); console.log('Launching...'); - + if (autorun) open(autorunUrl.toString()); console.log('SillyTavern is listening on: ' + tavernUrl); if (listen &&