mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
safe character renaming
- syncs /chats/ and sprites folders with char rename - disengages on invald/blank names - won't save over pre-existing files/folders - won't update character as long as bad name exists in #name_div - needs error handling to inform UI of bad names - not adapted to update groups yet
This commit is contained in:
@ -1415,6 +1415,7 @@
|
|||||||
<h4>Character Name</h4>
|
<h4>Character Name</h4>
|
||||||
<input id="character_name_pole" name="ch_name" class="text_pole" placeholder="Name this character" maxlength="50" value="" autocomplete="off">
|
<input id="character_name_pole" name="ch_name" class="text_pole" placeholder="Name this character" maxlength="50" value="" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="avatar_div" class="avatar_div">
|
<div id="avatar_div" class="avatar_div">
|
||||||
<div id="avatar_div_div" class="avatar">
|
<div id="avatar_div_div" class="avatar">
|
||||||
<img id="avatar_load_preview" src="img/ai4.png" alt="avatar">
|
<img id="avatar_load_preview" src="img/ai4.png" alt="avatar">
|
||||||
@ -1424,6 +1425,7 @@
|
|||||||
<input type="file" id="add_avatar_button" name="avatar" accept="image/png, image/jpeg, image/jpg, image/gif, image/bmp">
|
<input type="file" id="add_avatar_button" name="avatar" accept="image/png, image/jpeg, image/jpg, image/gif, image/bmp">
|
||||||
</label>
|
</label>
|
||||||
<div id="rm_button_back" class="menu_button fa-solid fa-left-long "></div>
|
<div id="rm_button_back" class="menu_button fa-solid fa-left-long "></div>
|
||||||
|
<div id="renameCharButton" class="menu_button fa-solid fa-user-pen" title="Rename Character"></div>
|
||||||
<div id="favorite_button" class="menu_button fa-solid fa-star" title="Add to Favorites"></div>
|
<div id="favorite_button" class="menu_button fa-solid fa-star" title="Add to Favorites"></div>
|
||||||
<input type="hidden" id="fav_checkbox" name="fav" />
|
<input type="hidden" id="fav_checkbox" name="fav" />
|
||||||
<div id="advanced_div" class="menu_button fa-solid fa-book " title="Advanced Definitions"></div>
|
<div id="advanced_div" class="menu_button fa-solid fa-book " title="Advanced Definitions"></div>
|
||||||
|
@ -772,7 +772,7 @@ async function setBackground(bg) {
|
|||||||
bg: bg,
|
bg: bg,
|
||||||
}),
|
}),
|
||||||
beforeSend: function () {
|
beforeSend: function () {
|
||||||
//$('#create_button').attr('value','Creating...'); //
|
|
||||||
},
|
},
|
||||||
cache: false,
|
cache: false,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
@ -2008,7 +2008,7 @@ async function Generate(type, automatic_trigger, force_name2) {
|
|||||||
url: generate_url, //
|
url: generate_url, //
|
||||||
data: JSON.stringify(generate_data),
|
data: JSON.stringify(generate_data),
|
||||||
beforeSend: function () {
|
beforeSend: function () {
|
||||||
//$('#create_button').attr('value','Creating...');
|
|
||||||
},
|
},
|
||||||
cache: false,
|
cache: false,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
@ -2427,7 +2427,7 @@ async function saveChat(chat_name, withMetadata) {
|
|||||||
avatar_url: characters[this_chid].avatar,
|
avatar_url: characters[this_chid].avatar,
|
||||||
}),
|
}),
|
||||||
beforeSend: function () {
|
beforeSend: function () {
|
||||||
//$('#create_button').attr('value','Creating...');
|
|
||||||
},
|
},
|
||||||
cache: false,
|
cache: false,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
@ -3020,7 +3020,7 @@ async function getAllCharaChats() {
|
|||||||
url: "/getallchatsofcharacter",
|
url: "/getallchatsofcharacter",
|
||||||
data: JSON.stringify({ avatar_url: characters[this_chid].avatar }),
|
data: JSON.stringify({ avatar_url: characters[this_chid].avatar }),
|
||||||
beforeSend: function () {
|
beforeSend: function () {
|
||||||
//$('#create_button').attr('value','Creating...');
|
|
||||||
},
|
},
|
||||||
cache: false,
|
cache: false,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
@ -3086,7 +3086,7 @@ async function getStatusNovel() {
|
|||||||
url: "/getstatus_novelai", //
|
url: "/getstatus_novelai", //
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data),
|
||||||
beforeSend: function () {
|
beforeSend: function () {
|
||||||
//$('#create_button').attr('value','Creating...');
|
|
||||||
},
|
},
|
||||||
cache: false,
|
cache: false,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
@ -3177,7 +3177,7 @@ function select_selected_character(chid) {
|
|||||||
$("#rm_button_back").css("display", "none");
|
$("#rm_button_back").css("display", "none");
|
||||||
//$("#character_import_button").css("display", "none");
|
//$("#character_import_button").css("display", "none");
|
||||||
$("#create_button").attr("value", "Save"); // what is the use case for this?
|
$("#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);
|
$("#rm_button_selected_ch").children("h2").text(display_name);
|
||||||
$("#add_avatar_button").val("");
|
$("#add_avatar_button").val("");
|
||||||
@ -3206,7 +3206,9 @@ function select_selected_character(chid) {
|
|||||||
updateFavButtonState(characters[chid].fav == "true");
|
updateFavButtonState(characters[chid].fav == "true");
|
||||||
|
|
||||||
$("#avatar_load_preview").attr("src", this_avatar);
|
$("#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");
|
$("#form_create").attr("actiontype", "editcharacter");
|
||||||
active_character = chid;
|
active_character = chid;
|
||||||
@ -3254,7 +3256,9 @@ function select_rm_create() {
|
|||||||
}
|
}
|
||||||
$("#avatar_div").css("display", "flex");
|
$("#avatar_div").css("display", "flex");
|
||||||
$("#avatar_load_preview").attr("src", default_avatar);
|
$("#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");
|
$("#form_create").attr("actiontype", "createcharacter");
|
||||||
}
|
}
|
||||||
@ -4264,13 +4268,19 @@ $(document).ready(function () {
|
|||||||
url: "/editcharacter",
|
url: "/editcharacter",
|
||||||
data: formData,
|
data: formData,
|
||||||
beforeSend: function () {
|
beforeSend: function () {
|
||||||
$("#create_button").attr("disabled", true);
|
//$("#create_button").attr("disabled", true);
|
||||||
$("#create_button").attr("value", "Save");
|
$("#create_button").attr("value", "Save");
|
||||||
},
|
},
|
||||||
cache: false,
|
cache: false,
|
||||||
contentType: false,
|
contentType: false,
|
||||||
processData: false,
|
processData: false,
|
||||||
success: function (html) {
|
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 () {
|
$(".mes").each(function () {
|
||||||
if ($(this).attr("is_system") == 'true') {
|
if ($(this).attr("is_system") == 'true') {
|
||||||
return;
|
return;
|
||||||
@ -4320,6 +4330,8 @@ $(document).ready(function () {
|
|||||||
error: function (jqXHR, exception) {
|
error: function (jqXHR, exception) {
|
||||||
$("#create_button").removeAttr("disabled");
|
$("#create_button").removeAttr("disabled");
|
||||||
$("#result_info").html("<font color=red>Error: no connection</font>");
|
$("#result_info").html("<font color=red>Error: no connection</font>");
|
||||||
|
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 () {
|
$("#talkativeness_slider").on("input", function () {
|
||||||
if (menu_type == "create") {
|
if (menu_type == "create") {
|
||||||
create_save_talkativeness = $("#talkativeness_slider").val();
|
create_save_talkativeness = $("#talkativeness_slider").val();
|
||||||
|
@ -925,6 +925,14 @@ select option:not(:checked) {
|
|||||||
color: #ffff00 !important;
|
color: #ffff00 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.displayBlock {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.displayNone {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
#api_url_text,
|
#api_url_text,
|
||||||
#textgenerationwebui_api_url_text {
|
#textgenerationwebui_api_url_text {
|
||||||
/*margin-right: 4px;*/
|
/*margin-right: 4px;*/
|
||||||
|
73
server.js
73
server.js
@ -677,22 +677,87 @@ app.post("/createcharacter", urlencodedParser, function (request, response) {
|
|||||||
|
|
||||||
|
|
||||||
app.post("/editcharacter", urlencodedParser, async 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;
|
let filedata = request.file;
|
||||||
//console.log(filedata.mimetype);
|
//console.log(filedata.mimetype);
|
||||||
var fileType = ".png";
|
var fileType = ".png";
|
||||||
var img_file = "ai";
|
var img_file = "ai";
|
||||||
var img_path = charactersPath;
|
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": ''};
|
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.chat = request.body.chat;
|
||||||
char.create_date = request.body.create_date;
|
char.create_date = request.body.create_date;
|
||||||
char = JSON.stringify(char);
|
char = JSON.stringify(char);
|
||||||
let target_img = (request.body.avatar_url).replace('.png', '');
|
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 {
|
try {
|
||||||
if (!filedata) {
|
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');
|
await charaWrite(img_path + request.body.avatar_url, char, target_img, response, 'Character saved');
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//console.log(filedata.filename);
|
//console.log(filedata.filename);
|
||||||
img_path = "uploads/";
|
img_path = "uploads/";
|
||||||
@ -704,8 +769,10 @@ app.post("/editcharacter", urlencodedParser, async function (request, response)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
return response.send(400);
|
//return response.send(400);
|
||||||
|
console.error('An error occured, character edit invalidated.');
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
app.post("/deletecharacter", urlencodedParser, function (request, response) {
|
app.post("/deletecharacter", urlencodedParser, function (request, response) {
|
||||||
if (!request.body || !request.body.avatar_url) {
|
if (!request.body || !request.body.avatar_url) {
|
||||||
|
Reference in New Issue
Block a user