mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-02-07 23:58:42 +01:00
Merge branch 'feature/exorcism' of https://github.com/city-unit/SillyTavern into feature/exorcism
This commit is contained in:
commit
82adc4c780
@ -2378,10 +2378,6 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
||||
abortController = new AbortController();
|
||||
}
|
||||
|
||||
if (main_api == 'novel' && quiet_prompt) {
|
||||
quiet_prompt = adjustNovelInstructionPrompt(quiet_prompt);
|
||||
}
|
||||
|
||||
// OpenAI doesn't need instruct mode. Use OAI main prompt instead.
|
||||
const isInstruct = power_user.instruct.enabled && main_api !== 'openai';
|
||||
const isImpersonate = type == "impersonate";
|
||||
@ -2470,6 +2466,11 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
||||
}
|
||||
}
|
||||
|
||||
if (quiet_prompt) {
|
||||
quiet_prompt = substituteParams(quiet_prompt);
|
||||
quiet_prompt = main_api == 'novel' ? adjustNovelInstructionPrompt(quiet_prompt) : quiet_prompt;
|
||||
}
|
||||
|
||||
if (true === dryRun ||
|
||||
(online_status != 'no_connection' && this_chid != undefined && this_chid !== 'invalid-safety-id')) {
|
||||
let textareaText;
|
||||
@ -7517,7 +7518,7 @@ $(document).ready(function () {
|
||||
$("#character_search_bar").val("").trigger("input");
|
||||
});
|
||||
|
||||
$(document).on("click", ".character_select", function() {
|
||||
$(document).on("click", ".character_select", function () {
|
||||
const id = $(this).attr("chid");
|
||||
selectCharacterById(id);
|
||||
});
|
||||
|
@ -1,5 +1,4 @@
|
||||
import {
|
||||
substituteParams,
|
||||
saveSettingsDebounced,
|
||||
systemUserName,
|
||||
hideSwipeButtons,
|
||||
@ -513,7 +512,7 @@ function getQuietPrompt(mode, trigger) {
|
||||
return trigger;
|
||||
}
|
||||
|
||||
return substituteParams(stringFormat(extension_settings.sd.prompts[mode], trigger));
|
||||
return stringFormat(extension_settings.sd.prompts[mode], trigger);
|
||||
}
|
||||
|
||||
function processReply(str) {
|
||||
@ -588,7 +587,7 @@ async function generatePicture(_, trigger, message, callback) {
|
||||
const callbackOriginal = callback;
|
||||
callback = async function (prompt, base64Image) {
|
||||
const imagePath = base64Image;
|
||||
const imgUrl = `url(${base64Image})`;
|
||||
const imgUrl = `url('${encodeURIComponent(base64Image)}')`;
|
||||
|
||||
if ('forceSetBackground' in window) {
|
||||
forceSetBackground(imgUrl);
|
||||
@ -652,7 +651,7 @@ async function generatePrompt(quiet_prompt) {
|
||||
return processReply(reply);
|
||||
}
|
||||
|
||||
async function sendGenerationRequest(generationType, prompt, characterName=null, callback) {
|
||||
async function sendGenerationRequest(generationType, prompt, characterName = null, callback) {
|
||||
const prefix = generationType !== generationMode.BACKGROUND
|
||||
? combinePrefixes(extension_settings.sd.prompt_prefix, getCharacterPrefix())
|
||||
: extension_settings.sd.prompt_prefix;
|
||||
@ -665,15 +664,15 @@ async function sendGenerationRequest(generationType, prompt, characterName=null,
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an "extras" image using a provided prompt and other settings,
|
||||
* Generates an "extras" image using a provided prompt and other settings,
|
||||
* then saves the generated image and either invokes a callback or sends a message with the image.
|
||||
*
|
||||
*
|
||||
* @param {string} prompt - The main instruction used to guide the image generation.
|
||||
* @param {string} prefix - Additional context or prefix to guide the image generation.
|
||||
* @param {string} characterName - The name used to determine the sub-directory for saving.
|
||||
* @param {function} [callback] - Optional callback function invoked with the prompt and saved image.
|
||||
* If not provided, `sendMessage` is called instead.
|
||||
*
|
||||
*
|
||||
* @returns {Promise<void>} - A promise that resolves when the image generation and processing are complete.
|
||||
*/
|
||||
async function generateExtrasImage(prompt, prefix, characterName, callback) {
|
||||
@ -702,7 +701,7 @@ async function generateExtrasImage(prompt, prefix, characterName, callback) {
|
||||
const data = await result.json();
|
||||
//filename should be character name + human readable timestamp + generation mode
|
||||
const filename = `${characterName}_${humanizedDateTime()}`;
|
||||
const base64Image = await saveBase64AsFile(data.image, characterName, filename, "jpg");
|
||||
const base64Image = await saveBase64AsFile(data.image, characterName, filename, "jpg");
|
||||
callback ? callback(prompt, base64Image) : sendMessage(prompt, base64Image);
|
||||
} else {
|
||||
callPopup('Image generation has failed. Please try again.', 'text');
|
||||
@ -710,15 +709,15 @@ async function generateExtrasImage(prompt, prefix, characterName, callback) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a "horde" image using the provided prompt and configuration settings,
|
||||
* Generates a "horde" image using the provided prompt and configuration settings,
|
||||
* then saves the generated image and either invokes a callback or sends a message with the image.
|
||||
*
|
||||
*
|
||||
* @param {string} prompt - The main instruction used to guide the image generation.
|
||||
* @param {string} prefix - Additional context or prefix to guide the image generation.
|
||||
* @param {string} characterName - The name used to determine the sub-directory for saving.
|
||||
* @param {function} [callback] - Optional callback function invoked with the prompt and saved image.
|
||||
* If not provided, `sendMessage` is called instead.
|
||||
*
|
||||
*
|
||||
* @returns {Promise<void>} - A promise that resolves when the image generation and processing are complete.
|
||||
*/
|
||||
async function generateHordeImage(prompt, prefix, characterName, callback) {
|
||||
@ -744,7 +743,7 @@ async function generateHordeImage(prompt, prefix, characterName, callback) {
|
||||
if (result.ok) {
|
||||
const data = await result.text();
|
||||
const filename = `${characterName}_${humanizedDateTime()}`;
|
||||
const base64Image = await saveBase64AsFile(data, characterName, filename, "webp");
|
||||
const base64Image = await saveBase64AsFile(data, characterName, filename, "webp");
|
||||
callback ? callback(prompt, base64Image) : sendMessage(prompt, base64Image);
|
||||
} else {
|
||||
toastr.error('Image generation has failed. Please try again.');
|
||||
@ -862,7 +861,7 @@ async function sdMessageButton(e) {
|
||||
const message_id = $mes.attr('mesid');
|
||||
const message = context.chat[message_id];
|
||||
const characterName = message?.name || context.name2;
|
||||
const messageText = substituteParams(message?.mes);
|
||||
const messageText = message?.mes;
|
||||
const hasSavedImage = message?.extra?.image && message?.extra?.title;
|
||||
|
||||
if ($icon.hasClass(busyClass)) {
|
||||
|
@ -337,25 +337,25 @@ async function getGroups() {
|
||||
}
|
||||
|
||||
export function getGroupBlock(group) {
|
||||
const template = $("#group_list_template .group_select").clone();
|
||||
template.data("id", group.id);
|
||||
template.attr("grid", group.id);
|
||||
template.find(".ch_name").html(group.name);
|
||||
template.find('.group_fav_icon').css("display", 'none');
|
||||
template.addClass(group.fav ? 'is_fav' : '');
|
||||
template.find(".ch_fav").val(group.fav);
|
||||
const template = $("#group_list_template .group_select").clone();
|
||||
template.data("id", group.id);
|
||||
template.attr("grid", group.id);
|
||||
template.find(".ch_name").html(group.name);
|
||||
template.find('.group_fav_icon').css("display", 'none');
|
||||
template.addClass(group.fav ? 'is_fav' : '');
|
||||
template.find(".ch_fav").val(group.fav);
|
||||
|
||||
// Display inline tags
|
||||
const tags = getTagsList(group.id);
|
||||
const tagsElement = template.find('.tags');
|
||||
tags.forEach(tag => appendTagToList(tagsElement, tag, {}));
|
||||
// Display inline tags
|
||||
const tags = getTagsList(group.id);
|
||||
const tagsElement = template.find('.tags');
|
||||
tags.forEach(tag => appendTagToList(tagsElement, tag, {}));
|
||||
|
||||
const avatar = getGroupAvatar(group);
|
||||
if (avatar) {
|
||||
$(template).find(".avatar").replaceWith(avatar);
|
||||
}
|
||||
const avatar = getGroupAvatar(group);
|
||||
if (avatar) {
|
||||
$(template).find(".avatar").replaceWith(avatar);
|
||||
}
|
||||
|
||||
return template;
|
||||
return template;
|
||||
}
|
||||
|
||||
function updateGroupAvatar(group) {
|
||||
@ -363,7 +363,7 @@ function updateGroupAvatar(group) {
|
||||
|
||||
$(".group_select").each(function () {
|
||||
if ($(this).data("id") == group.id) {
|
||||
$(this).find(".avatar").replaceWith(getGroupAvatar(group));
|
||||
$(this).find(".avatar").replaceWith(getGroupAvatar(group));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -382,7 +382,7 @@ function getGroupAvatar(group) {
|
||||
if (!group) {
|
||||
return $(`<div class="avatar"><img src="${default_avatar}"></div>`);
|
||||
}
|
||||
// if isDataURL or if it's a valid local file url
|
||||
// if isDataURL or if it's a valid local file url
|
||||
if (isValidImageUrl(group.avatar_url)) {
|
||||
return $(`<div class="avatar"><img src="${group.avatar_url}"></div>`);
|
||||
}
|
||||
@ -1132,16 +1132,16 @@ function select_group_chats(groupId, skipAnimation) {
|
||||
$("#rm_group_automode_label").hide();
|
||||
}
|
||||
|
||||
eventSource.emit('groupSelected', {detail: {id: openGroupId, group: group}});
|
||||
eventSource.emit('groupSelected', { detail: { id: openGroupId, group: group } });
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the upload and processing of a group avatar.
|
||||
* The selected image is read, cropped using a popup, processed into a thumbnail,
|
||||
* and then uploaded to the server.
|
||||
*
|
||||
*
|
||||
* @param {Event} event - The event triggered by selecting a file input, containing the image file to upload.
|
||||
*
|
||||
*
|
||||
* @returns {Promise<void>} - A promise that resolves when the processing and upload is complete.
|
||||
*/
|
||||
async function uploadGroupAvatar(event) {
|
||||
|
@ -557,15 +557,15 @@ export function extractDataFromPng(data, identifier = 'chara') {
|
||||
|
||||
/**
|
||||
* Sends a base64 encoded image to the backend to be saved as a file.
|
||||
*
|
||||
*
|
||||
* @param {string} base64Data - The base64 encoded image data.
|
||||
* @param {string} characterName - The character name to determine the sub-directory for saving.
|
||||
* @param {string} ext - The file extension for the image (e.g., 'jpg', 'png', 'webp').
|
||||
*
|
||||
* @returns {Promise<string>} - Resolves to the saved image's path on the server.
|
||||
*
|
||||
* @returns {Promise<string>} - Resolves to the saved image's path on the server.
|
||||
* Rejects with an error if the upload fails.
|
||||
*/
|
||||
export async function saveBase64AsFile(base64Data, characterName, filename="", ext) {
|
||||
export async function saveBase64AsFile(base64Data, characterName, filename = "", ext) {
|
||||
// Construct the full data URL
|
||||
const format = ext; // Extract the file extension (jpg, png, webp)
|
||||
const dataURL = `data:image/${format};base64,${base64Data}`;
|
||||
|
12
server.js
12
server.js
@ -2617,7 +2617,7 @@ app.post('/uploaduseravatar', urlencodedParser, async (request, response) => {
|
||||
/**
|
||||
* Ensure the directory for the provided file path exists.
|
||||
* If not, it will recursively create the directory.
|
||||
*
|
||||
*
|
||||
* @param {string} filePath - The full path of the file for which the directory should be ensured.
|
||||
*/
|
||||
function ensureDirectoryExistence(filePath) {
|
||||
@ -2633,7 +2633,7 @@ function ensureDirectoryExistence(filePath) {
|
||||
* Endpoint to handle image uploads.
|
||||
* The image should be provided in the request body in base64 format.
|
||||
* Optionally, a character name can be provided to save the image in a sub-folder.
|
||||
*
|
||||
*
|
||||
* @route POST /uploadimage
|
||||
* @param {Object} request.body - The request payload.
|
||||
* @param {string} request.body.image - The base64 encoded image data.
|
||||
@ -2656,13 +2656,13 @@ app.post('/uploadimage', jsonParser, async (request, response) => {
|
||||
|
||||
// Constructing filename and path
|
||||
let filename = `${Date.now()}.${format}`;
|
||||
if(request.body.filename){
|
||||
if (request.body.filename) {
|
||||
filename = `${request.body.filename}.${format}`;
|
||||
}
|
||||
|
||||
// if character is defined, save to a sub folder for that character
|
||||
let pathToNewFile = path.join(directories.userImages, filename);
|
||||
if(request.body.ch_name){
|
||||
let pathToNewFile = path.join(directories.userImages, filename);
|
||||
if (request.body.ch_name) {
|
||||
pathToNewFile = path.join(directories.userImages, request.body.ch_name, filename);
|
||||
}
|
||||
|
||||
@ -2672,7 +2672,7 @@ app.post('/uploadimage', jsonParser, async (request, response) => {
|
||||
await fs.promises.writeFile(pathToNewFile, imageBuffer);
|
||||
// send the path to the image, relative to the client folder, which means removing the first folder from the path which is 'public'
|
||||
pathToNewFile = pathToNewFile.split(path.sep).slice(1).join(path.sep);
|
||||
response.send({ path:pathToNewFile });
|
||||
response.send({ path: pathToNewFile });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
response.status(500).send({ error: "Failed to save the image" });
|
||||
|
Loading…
x
Reference in New Issue
Block a user