mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Add cropping of user and characters avatars. Prevent failures on webp import (Android)
This commit is contained in:
198
public/script.js
198
public/script.js
@@ -239,6 +239,7 @@ let exportPopper = Popper.createPopper(document.getElementById('export_button'),
|
|||||||
let dialogueResolve = null;
|
let dialogueResolve = null;
|
||||||
let chat_metadata = {};
|
let chat_metadata = {};
|
||||||
let streamingProcessor = null;
|
let streamingProcessor = null;
|
||||||
|
let crop_data = undefined;
|
||||||
|
|
||||||
let fav_ch_checked = false;
|
let fav_ch_checked = false;
|
||||||
|
|
||||||
@@ -2821,60 +2822,67 @@ async function saveChat(chat_name, withMetadata) {
|
|||||||
|
|
||||||
async function read_avatar_load(input) {
|
async function read_avatar_load(input) {
|
||||||
if (input.files && input.files[0]) {
|
if (input.files && input.files[0]) {
|
||||||
const reader = new FileReader();
|
|
||||||
if (selected_button == "create") {
|
if (selected_button == "create") {
|
||||||
create_save_avatar = input.files;
|
create_save_avatar = input.files;
|
||||||
}
|
}
|
||||||
reader.onload = async function (e) {
|
|
||||||
/* $('#dialogue_popup').addClass('large_dialogue_popup');
|
|
||||||
$('#dialogue_popup').addClass('wide_dialogue_popup');
|
|
||||||
|
|
||||||
await callPopup(`
|
|
||||||
<h3>Click image to start cropping. Click Ok to finalize</h3>
|
|
||||||
<div id='avatarCropWrap'>
|
|
||||||
<img id='avatarToCrop' src='${e.target.result}'>
|
|
||||||
</div>
|
|
||||||
`, 'avatarToCrop'); */
|
|
||||||
|
|
||||||
$("#avatar_load_preview").attr("src", e.target.result);
|
const e = await new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = resolve;
|
||||||
|
reader.onerror = reject;
|
||||||
|
reader.readAsDataURL(input.files[0]);
|
||||||
|
})
|
||||||
|
|
||||||
if (menu_type != "create") {
|
$('#dialogue_popup').addClass('large_dialogue_popup wide_dialogue_popup');
|
||||||
$("#create_button").trigger('click');
|
|
||||||
|
|
||||||
const formData = new FormData($("#form_create").get(0));
|
const croppedImage = await callPopup(getCropPopup(e.target.result), 'avatarToCrop');
|
||||||
|
|
||||||
$(".mes").each(async function () {
|
$("#avatar_load_preview").attr("src", croppedImage || e.target.result);
|
||||||
if ($(this).attr("is_system") == 'true') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ($(this).attr("is_user") == 'true') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ($(this).attr("ch_name") == formData.get('ch_name')) {
|
|
||||||
const previewSrc = $("#avatar_load_preview").attr("src");
|
|
||||||
const avatar = $(this).find(".avatar img");
|
|
||||||
avatar.attr('src', default_avatar);
|
|
||||||
await delay(1);
|
|
||||||
avatar.attr('src', previewSrc);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await delay(durationSaveEdit);
|
if (menu_type == "create") {
|
||||||
await fetch(getThumbnailUrl('avatar', formData.get('avatar_url')), {
|
return;
|
||||||
method: 'GET',
|
}
|
||||||
headers: {
|
|
||||||
'pragma': 'no-cache',
|
$("#create_button").trigger('click');
|
||||||
'cache-control': 'no-cache',
|
|
||||||
}
|
const formData = new FormData($("#form_create").get(0));
|
||||||
});
|
|
||||||
console.log('Avatar refreshed');
|
$(".mes").each(async function () {
|
||||||
|
if ($(this).attr("is_system") == 'true') {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
};
|
if ($(this).attr("is_user") == 'true') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($(this).attr("ch_name") == formData.get('ch_name')) {
|
||||||
|
const previewSrc = $("#avatar_load_preview").attr("src");
|
||||||
|
const avatar = $(this).find(".avatar img");
|
||||||
|
avatar.attr('src', default_avatar);
|
||||||
|
await delay(1);
|
||||||
|
avatar.attr('src', previewSrc);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await delay(durationSaveEdit);
|
||||||
|
await fetch(getThumbnailUrl('avatar', formData.get('avatar_url')), {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'pragma': 'no-cache',
|
||||||
|
'cache-control': 'no-cache',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log('Avatar refreshed');
|
||||||
|
|
||||||
reader.readAsDataURL(input.files[0]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCropPopup(src) {
|
||||||
|
return `<h3>Set the crop position of the avatar image and click Ok to confirm.</h3>
|
||||||
|
<div id='avatarCropWrap'>
|
||||||
|
<img id='avatarToCrop' src='${src}'>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
function getThumbnailUrl(type, file) {
|
function getThumbnailUrl(type, file) {
|
||||||
return `/thumbnail?type=${type}&file=${encodeURIComponent(file)}`;
|
return `/thumbnail?type=${type}&file=${encodeURIComponent(file)}`;
|
||||||
}
|
}
|
||||||
@@ -3736,10 +3744,6 @@ function callPopup(text, type, inputValue = '') {
|
|||||||
|
|
||||||
$("#dialogue_popup_input").val(inputValue);
|
$("#dialogue_popup_input").val(inputValue);
|
||||||
|
|
||||||
if (popup_type == 'avatarToCrop') {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (popup_type == 'input') {
|
if (popup_type == 'input') {
|
||||||
$("#dialogue_popup_input").css("display", "block");
|
$("#dialogue_popup_input").css("display", "block");
|
||||||
$("#dialogue_popup_ok").text("Save");
|
$("#dialogue_popup_ok").text("Save");
|
||||||
@@ -3753,6 +3757,17 @@ function callPopup(text, type, inputValue = '') {
|
|||||||
if (popup_type == 'input') {
|
if (popup_type == 'input') {
|
||||||
$("#dialogue_popup_input").focus();
|
$("#dialogue_popup_input").focus();
|
||||||
}
|
}
|
||||||
|
if (popup_type == 'avatarToCrop') {
|
||||||
|
// unset existing data
|
||||||
|
crop_data = undefined;
|
||||||
|
|
||||||
|
$('#avatarToCrop').cropper({
|
||||||
|
aspectRatio: 2 / 3,
|
||||||
|
crop: function (event) {
|
||||||
|
crop_data = event.detail;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
$("#shadow_popup").transition({
|
$("#shadow_popup").transition({
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
duration: 200,
|
duration: 200,
|
||||||
@@ -4403,7 +4418,7 @@ $(document).ready(function () {
|
|||||||
$(document).on("click", "#user_avatar_block .avatar_upload", function () {
|
$(document).on("click", "#user_avatar_block .avatar_upload", function () {
|
||||||
$("#avatar_upload_file").click();
|
$("#avatar_upload_file").click();
|
||||||
});
|
});
|
||||||
$("#avatar_upload_file").on("change", function (e) {
|
$("#avatar_upload_file").on("change", async function (e) {
|
||||||
const file = e.target.files[0];
|
const file = e.target.files[0];
|
||||||
|
|
||||||
if (!file) {
|
if (!file) {
|
||||||
@@ -4412,9 +4427,25 @@ $(document).ready(function () {
|
|||||||
|
|
||||||
const formData = new FormData($("#form_upload_avatar").get(0));
|
const formData = new FormData($("#form_upload_avatar").get(0));
|
||||||
|
|
||||||
|
const dataUrl = await new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = resolve;
|
||||||
|
reader.onerror = reject;
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#dialogue_popup').addClass('large_dialogue_popup wide_dialogue_popup');
|
||||||
|
await callPopup(getCropPopup(dataUrl.target.result), 'avatarToCrop');
|
||||||
|
|
||||||
|
let url = "/uploaduseravatar";
|
||||||
|
|
||||||
|
if (crop_data !== undefined) {
|
||||||
|
url += `?crop=${encodeURIComponent(JSON.stringify(crop_data))}`;
|
||||||
|
}
|
||||||
|
|
||||||
jQuery.ajax({
|
jQuery.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/uploaduseravatar",
|
url: url,
|
||||||
data: formData,
|
data: formData,
|
||||||
beforeSend: () => { },
|
beforeSend: () => { },
|
||||||
cache: false,
|
cache: false,
|
||||||
@@ -4424,6 +4455,7 @@ $(document).ready(function () {
|
|||||||
if (data.path) {
|
if (data.path) {
|
||||||
appendUserAvatar(data.path);
|
appendUserAvatar(data.path);
|
||||||
}
|
}
|
||||||
|
crop_data = undefined;
|
||||||
},
|
},
|
||||||
error: (jqXHR, exception) => { },
|
error: (jqXHR, exception) => { },
|
||||||
});
|
});
|
||||||
@@ -4522,32 +4554,7 @@ $(document).ready(function () {
|
|||||||
// $("#shadow_popup").css("opacity:", 0.0);
|
// $("#shadow_popup").css("opacity:", 0.0);
|
||||||
|
|
||||||
if (popup_type == 'avatarToCrop') {
|
if (popup_type == 'avatarToCrop') {
|
||||||
|
dialogueResolve($("#avatarToCrop").data('cropper').getCroppedCanvas().toDataURL('image/jpeg'));
|
||||||
//ideally this is where we would grab the crop coordinates
|
|
||||||
//and send back to read_avatar_load() to be sent to server for actual file resizing/cropping.
|
|
||||||
//the code below does not work 'cropper not defined'.
|
|
||||||
|
|
||||||
$("#avatarToCrop").cropper.getCroppedCanvas();
|
|
||||||
|
|
||||||
$("#avatarToCrop").cropper.getCroppedCanvas({
|
|
||||||
width: 160,
|
|
||||||
height: 90,
|
|
||||||
minWidth: 400,
|
|
||||||
minHeight: 600,
|
|
||||||
maxWidth: 4096,
|
|
||||||
maxHeight: 4096,
|
|
||||||
fillColor: 'transparent',
|
|
||||||
imageSmoothingEnabled: false,
|
|
||||||
imageSmoothingQuality: 'high',
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#avatarToCrop").cropper.getCroppedCanvas().toBlob((blob) => {
|
|
||||||
currentCroppedAvatar = new FormData();
|
|
||||||
currentCroppedAvatar.append('croppedImage', blob/*, 'example.png' */);
|
|
||||||
});
|
|
||||||
|
|
||||||
return currentCroppedAvatar;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (popup_type == "del_bg") {
|
if (popup_type == "del_bg") {
|
||||||
@@ -4705,10 +4712,15 @@ $(document).ready(function () {
|
|||||||
if ($("#form_create").attr("actiontype") == "createcharacter") {
|
if ($("#form_create").attr("actiontype") == "createcharacter") {
|
||||||
if ($("#character_name_pole").val().length > 0) {
|
if ($("#character_name_pole").val().length > 0) {
|
||||||
//if the character name text area isn't empty (only posible when creating a new character)
|
//if the character name text area isn't empty (only posible when creating a new character)
|
||||||
//console.log('/createcharacter entered');
|
let url = "/createcharacter";
|
||||||
|
|
||||||
|
if (crop_data != undefined) {
|
||||||
|
url += `?crop=${encodeURIComponent(JSON.stringify(crop_data))}`;
|
||||||
|
}
|
||||||
|
|
||||||
jQuery.ajax({
|
jQuery.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/createcharacter",
|
url: url,
|
||||||
data: formData,
|
data: formData,
|
||||||
beforeSend: function () {
|
beforeSend: function () {
|
||||||
$("#create_button").attr("disabled", true);
|
$("#create_button").attr("disabled", true);
|
||||||
@@ -4760,6 +4772,7 @@ $(document).ready(function () {
|
|||||||
select_rm_info(`Character created<br><h4>${DOMPurify.sanitize(save_name)}</h4>`, oldSelectedChar);
|
select_rm_info(`Character created<br><h4>${DOMPurify.sanitize(save_name)}</h4>`, oldSelectedChar);
|
||||||
|
|
||||||
$("#rm_info_block").transition({ opacity: 1.0, duration: 2000 });
|
$("#rm_info_block").transition({ opacity: 1.0, duration: 2000 });
|
||||||
|
crop_data = undefined;
|
||||||
},
|
},
|
||||||
error: function (jqXHR, exception) {
|
error: function (jqXHR, exception) {
|
||||||
$("#create_button").removeAttr("disabled");
|
$("#create_button").removeAttr("disabled");
|
||||||
@@ -4769,11 +4782,15 @@ $(document).ready(function () {
|
|||||||
$("#result_info").html("Name not entered");
|
$("#result_info").html("Name not entered");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//console.log('/editcharacter -- entered.');
|
let url = '/editcharacter';
|
||||||
//console.log('Avatar Button Value:'+$("#add_avatar_button").val());
|
|
||||||
|
if (crop_data != undefined) {
|
||||||
|
url += `?crop=${encodeURIComponent(JSON.stringify(crop_data))}`;
|
||||||
|
}
|
||||||
|
|
||||||
jQuery.ajax({
|
jQuery.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/editcharacter",
|
url: url,
|
||||||
data: formData,
|
data: formData,
|
||||||
beforeSend: function () {
|
beforeSend: function () {
|
||||||
//$("#create_button").attr("disabled", true);
|
//$("#create_button").attr("disabled", true);
|
||||||
@@ -4817,6 +4834,7 @@ $(document).ready(function () {
|
|||||||
$("#add_avatar_button").val("").clone(true)
|
$("#add_avatar_button").val("").clone(true)
|
||||||
);
|
);
|
||||||
$("#create_button").attr("value", "Save");
|
$("#create_button").attr("value", "Save");
|
||||||
|
crop_data = undefined;
|
||||||
},
|
},
|
||||||
error: function (jqXHR, exception) {
|
error: function (jqXHR, exception) {
|
||||||
$("#create_button").removeAttr("disabled");
|
$("#create_button").removeAttr("disabled");
|
||||||
@@ -5878,28 +5896,4 @@ $(document).ready(function () {
|
|||||||
$(masterElement).val(myValue).trigger('input');
|
$(masterElement).val(myValue).trigger('input');
|
||||||
restoreCaretPosition($(this).get(0), caretPosition);
|
restoreCaretPosition($(this).get(0), caretPosition);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* $("#dialogue_popup_text").on('click', '#avatarToCrop', function () {
|
|
||||||
|
|
||||||
var $image = $('#avatarToCrop');
|
|
||||||
|
|
||||||
$image.cropper({
|
|
||||||
aspectRatio: 3 / 4,
|
|
||||||
crop: function (event) {
|
|
||||||
console.log(event.detail.x);
|
|
||||||
console.log(event.detail.y);
|
|
||||||
console.log(event.detail.width);
|
|
||||||
console.log(event.detail.height);
|
|
||||||
console.log(event.detail.rotate);
|
|
||||||
console.log(event.detail.scaleX);
|
|
||||||
console.log(event.detail.scaleY);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get the Cropper.js instance after initialized
|
|
||||||
var cropper = $image.data('cropper');
|
|
||||||
|
|
||||||
|
|
||||||
}); */
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@@ -2617,7 +2617,7 @@ h5 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#avatarCropWrap {
|
#avatarCropWrap {
|
||||||
margin: 10px;
|
margin: 10px auto;
|
||||||
max-height: 90%;
|
max-height: 90%;
|
||||||
max-width: 90%;
|
max-width: 90%;
|
||||||
}
|
}
|
||||||
|
85
server.js
85
server.js
@@ -164,6 +164,8 @@ function humanizedISO8601DateTime() {
|
|||||||
var is_colab = process.env.colaburl !== undefined;
|
var is_colab = process.env.colaburl !== undefined;
|
||||||
var charactersPath = 'public/characters/';
|
var charactersPath = 'public/characters/';
|
||||||
var chatsPath = 'public/chats/';
|
var chatsPath = 'public/chats/';
|
||||||
|
const AVATAR_WIDTH = 400;
|
||||||
|
const AVATAR_HEIGHT = 600;
|
||||||
const jsonParser = express.json({ limit: '100mb' });
|
const jsonParser = express.json({ limit: '100mb' });
|
||||||
const urlencodedParser = express.urlencoded({ extended: true, limit: '100mb' });
|
const urlencodedParser = express.urlencoded({ extended: true, limit: '100mb' });
|
||||||
const baseRequestArgs = { headers: { "Content-Type": "application/json" } };
|
const baseRequestArgs = { headers: { "Content-Type": "application/json" } };
|
||||||
@@ -703,8 +705,9 @@ app.post("/createcharacter", urlencodedParser, function (request, response) {
|
|||||||
if (!request.file) {
|
if (!request.file) {
|
||||||
charaWrite(defaultAvatar, char, internalName, response, avatarName);
|
charaWrite(defaultAvatar, char, internalName, response, avatarName);
|
||||||
} else {
|
} else {
|
||||||
|
const crop = tryParse(request.query.crop);
|
||||||
const uploadPath = path.join("./uploads/", request.file.filename);
|
const uploadPath = path.join("./uploads/", request.file.filename);
|
||||||
charaWrite(uploadPath, char, internalName, response, avatarName);
|
charaWrite(uploadPath, char, internalName, response, avatarName, crop);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -799,9 +802,10 @@ app.post("/editcharacter", urlencodedParser, async function (request, response)
|
|||||||
const avatarPath = path.join(charactersPath, request.body.avatar_url);
|
const avatarPath = path.join(charactersPath, request.body.avatar_url);
|
||||||
await charaWrite(avatarPath, char, target_img, response, 'Character saved');
|
await charaWrite(avatarPath, char, target_img, response, 'Character saved');
|
||||||
} else {
|
} else {
|
||||||
|
const crop = tryParse(request.query.crop);
|
||||||
const newAvatarPath = path.join("./uploads/", request.file.filename);
|
const newAvatarPath = path.join("./uploads/", request.file.filename);
|
||||||
invalidateThumbnail('avatar', request.body.avatar_url);
|
invalidateThumbnail('avatar', request.body.avatar_url);
|
||||||
await charaWrite(newAvatarPath, char, target_img, response, 'Character saved');
|
await charaWrite(newAvatarPath, char, target_img, response, 'Character saved', crop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
@@ -845,11 +849,17 @@ app.post("/deletecharacter", urlencodedParser, function (request, response) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
async function charaWrite(img_url, data, target_img, response = undefined, mes = 'ok') {
|
async function charaWrite(img_url, data, target_img, response = undefined, mes = 'ok', crop = undefined) {
|
||||||
try {
|
try {
|
||||||
// Read the image, resize, and save it as a PNG into the buffer
|
// Read the image, resize, and save it as a PNG into the buffer
|
||||||
const rawImg = await jimp.read(img_url);
|
let rawImg = await jimp.read(img_url);
|
||||||
const image = await rawImg.cover(400, 600).getBufferAsync(jimp.MIME_PNG);
|
|
||||||
|
// Apply crop if defined
|
||||||
|
if (typeof crop == 'object') {
|
||||||
|
rawImg = rawImg.crop(crop.x, crop.y, crop.width, crop.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
const image = await rawImg.cover(AVATAR_WIDTH, AVATAR_HEIGHT).getBufferAsync(jimp.MIME_PNG);
|
||||||
|
|
||||||
// Get the chunks
|
// Get the chunks
|
||||||
const chunks = extract(image);
|
const chunks = extract(image);
|
||||||
@@ -1525,6 +1535,7 @@ app.post("/importcharacter", urlencodedParser, async function (request, response
|
|||||||
let filedata = request.file;
|
let filedata = request.file;
|
||||||
let uploadPath = path.join('./uploads', filedata.filename);
|
let uploadPath = path.join('./uploads', filedata.filename);
|
||||||
var format = request.body.file_type;
|
var format = request.body.file_type;
|
||||||
|
const defaultAvatarPath = './public/img/ai4.png';
|
||||||
//console.log(format);
|
//console.log(format);
|
||||||
if (filedata) {
|
if (filedata) {
|
||||||
if (format == 'json') {
|
if (format == 'json') {
|
||||||
@@ -1539,16 +1550,37 @@ app.post("/importcharacter", urlencodedParser, async function (request, response
|
|||||||
jsonData.name = sanitize(jsonData.name);
|
jsonData.name = sanitize(jsonData.name);
|
||||||
|
|
||||||
png_name = getPngName(jsonData.name);
|
png_name = getPngName(jsonData.name);
|
||||||
let char = { "name": jsonData.name, "description": jsonData.description ?? '', "personality": jsonData.personality ?? '', "first_mes": jsonData.first_mes ?? '', "avatar": 'none', "chat": jsonData.name + " - " + humanizedISO8601DateTime(), "mes_example": jsonData.mes_example ?? '', "scenario": jsonData.scenario ?? '', "create_date": humanizedISO8601DateTime(), "talkativeness": jsonData.talkativeness ?? 0.5 };
|
let char = {
|
||||||
|
"name": jsonData.name,
|
||||||
|
"description": jsonData.description ?? '',
|
||||||
|
"personality": jsonData.personality ?? '',
|
||||||
|
"first_mes": jsonData.first_mes ?? '',
|
||||||
|
"avatar": 'none', "chat": jsonData.name + " - " + humanizedISO8601DateTime(),
|
||||||
|
"mes_example": jsonData.mes_example ?? '',
|
||||||
|
"scenario": jsonData.scenario ?? '',
|
||||||
|
"create_date": humanizedISO8601DateTime(),
|
||||||
|
"talkativeness": jsonData.talkativeness ?? 0.5
|
||||||
|
};
|
||||||
char = JSON.stringify(char);
|
char = JSON.stringify(char);
|
||||||
charaWrite('./public/img/ai4.png', char, png_name, response, { file_name: png_name });
|
charaWrite(defaultAvatarPath, char, png_name, response, { file_name: png_name });
|
||||||
} else if (jsonData.char_name !== undefined) {//json Pygmalion notepad
|
} else if (jsonData.char_name !== undefined) {//json Pygmalion notepad
|
||||||
jsonData.char_name = sanitize(jsonData.char_name);
|
jsonData.char_name = sanitize(jsonData.char_name);
|
||||||
|
|
||||||
png_name = getPngName(jsonData.char_name);
|
png_name = getPngName(jsonData.char_name);
|
||||||
let char = { "name": jsonData.char_name, "description": jsonData.char_persona ?? '', "personality": '', "first_mes": jsonData.char_greeting ?? '', "avatar": 'none', "chat": jsonData.name + " - " + humanizedISO8601DateTime(), "mes_example": jsonData.example_dialogue ?? '', "scenario": jsonData.world_scenario ?? '', "create_date": humanizedISO8601DateTime(), "talkativeness": jsonData.talkativeness ?? 0.5 };
|
let char = {
|
||||||
|
"name": jsonData.char_name,
|
||||||
|
"description": jsonData.char_persona ?? '',
|
||||||
|
"personality": '',
|
||||||
|
"first_mes": jsonData.char_greeting ?? '',
|
||||||
|
"avatar": 'none',
|
||||||
|
"chat": jsonData.name + " - " + humanizedISO8601DateTime(),
|
||||||
|
"mes_example": jsonData.example_dialogue ?? '',
|
||||||
|
"scenario": jsonData.world_scenario ?? '',
|
||||||
|
"create_date": humanizedISO8601DateTime(),
|
||||||
|
"talkativeness": jsonData.talkativeness ?? 0.5
|
||||||
|
};
|
||||||
char = JSON.stringify(char);
|
char = JSON.stringify(char);
|
||||||
charaWrite('./public/img/ai4.png', char, png_name, response, { file_name: png_name });
|
charaWrite(defaultAvatarPath, char, png_name, response, { file_name: png_name });
|
||||||
} else {
|
} else {
|
||||||
console.log('Incorrect character format .json');
|
console.log('Incorrect character format .json');
|
||||||
response.send({ error: true });
|
response.send({ error: true });
|
||||||
@@ -1561,15 +1593,32 @@ app.post("/importcharacter", urlencodedParser, async function (request, response
|
|||||||
jsonData.name = sanitize(jsonData.name);
|
jsonData.name = sanitize(jsonData.name);
|
||||||
|
|
||||||
if (format == 'webp') {
|
if (format == 'webp') {
|
||||||
let convertedPath = path.join('./uploads', path.basename(uploadPath, ".webp") + ".png")
|
try {
|
||||||
await webp.dwebp(uploadPath, convertedPath, "-o");
|
let convertedPath = path.join('./uploads', path.basename(uploadPath, ".webp") + ".png")
|
||||||
uploadPath = convertedPath;
|
await webp.dwebp(uploadPath, convertedPath, "-o");
|
||||||
|
uploadPath = convertedPath;
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
console.error('WEBP image conversion failed. Using the default character image.');
|
||||||
|
uploadPath = defaultAvatarPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
png_name = getPngName(jsonData.name);
|
png_name = getPngName(jsonData.name);
|
||||||
|
|
||||||
if (jsonData.name !== undefined) {
|
if (jsonData.name !== undefined) {
|
||||||
let char = { "name": jsonData.name, "description": jsonData.description ?? '', "personality": jsonData.personality ?? '', "first_mes": jsonData.first_mes ?? '', "avatar": 'none', "chat": jsonData.name + " - " + humanizedISO8601DateTime(), "mes_example": jsonData.mes_example ?? '', "scenario": jsonData.scenario ?? '', "create_date": humanizedISO8601DateTime(), "talkativeness": jsonData.talkativeness ?? 0.5 };
|
let char = {
|
||||||
|
"name": jsonData.name,
|
||||||
|
"description": jsonData.description ?? '',
|
||||||
|
"personality": jsonData.personality ?? '',
|
||||||
|
"first_mes": jsonData.first_mes ?? '',
|
||||||
|
"avatar": 'none',
|
||||||
|
"chat": jsonData.name + " - " + humanizedISO8601DateTime(),
|
||||||
|
"mes_example": jsonData.mes_example ?? '',
|
||||||
|
"scenario": jsonData.scenario ?? '',
|
||||||
|
"create_date": humanizedISO8601DateTime(),
|
||||||
|
"talkativeness": jsonData.talkativeness ?? 0.5
|
||||||
|
};
|
||||||
char = JSON.stringify(char);
|
char = JSON.stringify(char);
|
||||||
await charaWrite(uploadPath, char, png_name, response, { file_name: png_name });
|
await charaWrite(uploadPath, char, png_name, response, { file_name: png_name });
|
||||||
}
|
}
|
||||||
@@ -1804,8 +1853,14 @@ app.post('/uploaduseravatar', urlencodedParser, async (request, response) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const pathToUpload = path.join('./uploads/' + request.file.filename);
|
const pathToUpload = path.join('./uploads/' + request.file.filename);
|
||||||
const rawImg = await jimp.read(pathToUpload);
|
const crop = tryParse(request.query.crop);
|
||||||
const image = await rawImg.cover(400, 400).getBufferAsync(jimp.MIME_PNG);
|
let rawImg = await jimp.read(pathToUpload);
|
||||||
|
|
||||||
|
if (typeof crop == 'object') {
|
||||||
|
rawImg = rawImg.crop(crop.x, crop.y, crop.width, crop.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
const image = await rawImg.cover(AVATAR_WIDTH, AVATAR_HEIGHT).getBufferAsync(jimp.MIME_PNG);
|
||||||
|
|
||||||
const filename = `${Date.now()}.png`;
|
const filename = `${Date.now()}.png`;
|
||||||
const pathToNewFile = path.join(directories.avatars, filename);
|
const pathToNewFile = path.join(directories.avatars, filename);
|
||||||
|
Reference in New Issue
Block a user