mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-02-10 17:10:45 +01:00
Update /ask with new char find functionality
This commit is contained in:
parent
ca009dee59
commit
d6e52dbb97
@ -247,7 +247,7 @@ export function initDefaultSlashCommands() {
|
|||||||
namedArgumentList: [
|
namedArgumentList: [
|
||||||
SlashCommandNamedArgument.fromProps({
|
SlashCommandNamedArgument.fromProps({
|
||||||
name: 'name',
|
name: 'name',
|
||||||
description: 'Character name',
|
description: 'Character name - or unique character identifier (avatar key)',
|
||||||
typeList: [ARGUMENT_TYPE.STRING],
|
typeList: [ARGUMENT_TYPE.STRING],
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
enumProvider: commonEnumProviders.characters('character'),
|
enumProvider: commonEnumProviders.characters('character'),
|
||||||
@ -255,7 +255,7 @@ export function initDefaultSlashCommands() {
|
|||||||
}),
|
}),
|
||||||
SlashCommandNamedArgument.fromProps({
|
SlashCommandNamedArgument.fromProps({
|
||||||
name: 'avatar',
|
name: 'avatar',
|
||||||
description: 'Character avatar override (Can be either avatar filename or just the character name to pull the avatar from)',
|
description: 'Character avatar override (Can be either avatar key or just the character name to pull the avatar from)',
|
||||||
typeList: [ARGUMENT_TYPE.STRING],
|
typeList: [ARGUMENT_TYPE.STRING],
|
||||||
enumProvider: commonEnumProviders.characters('character'),
|
enumProvider: commonEnumProviders.characters('character'),
|
||||||
}),
|
}),
|
||||||
@ -288,6 +288,9 @@ export function initDefaultSlashCommands() {
|
|||||||
<pre><code>/sendas name="Chloe" Hello, guys!</code></pre>
|
<pre><code>/sendas name="Chloe" Hello, guys!</code></pre>
|
||||||
will send "Hello, guys!" from "Chloe".
|
will send "Hello, guys!" from "Chloe".
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<pre><code>/sendas name="Chloe" avatar="BigBadBoss" Hehehe, I am the big bad evil, fear me.</code></pre>
|
||||||
|
will send a message as the character "Chloe", but utilizing the avatar from a character named "BigBadBoss".
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -509,7 +512,7 @@ export function initDefaultSlashCommands() {
|
|||||||
namedArgumentList: [
|
namedArgumentList: [
|
||||||
SlashCommandNamedArgument.fromProps({
|
SlashCommandNamedArgument.fromProps({
|
||||||
name: 'name',
|
name: 'name',
|
||||||
description: 'character name',
|
description: 'Character name - or unique character identifier (avatar key)',
|
||||||
typeList: [ARGUMENT_TYPE.STRING],
|
typeList: [ARGUMENT_TYPE.STRING],
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
enumProvider: commonEnumProviders.characters('character'),
|
enumProvider: commonEnumProviders.characters('character'),
|
||||||
@ -2558,26 +2561,22 @@ async function askCharacter(args, text) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = '';
|
if (!args.name) {
|
||||||
|
|
||||||
if (args?.name) {
|
|
||||||
name = args.name.trim();
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
toastr.warning('You must specify a name of the character to ask.');
|
toastr.warning('You must specify a name of the character to ask.');
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const prevChId = this_chid;
|
const prevChId = this_chid;
|
||||||
|
|
||||||
// Find the character
|
// Find the character
|
||||||
const chId = characters.findIndex((e) => e.name === name || e.avatar === name);
|
const character = findChar({ name: args?.name });
|
||||||
if (!characters[chId] || chId === -1) {
|
if (!character) {
|
||||||
toastr.error('Character not found.');
|
toastr.error('Character not found.');
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const chId = getCharIndex(character);
|
||||||
|
|
||||||
if (text) {
|
if (text) {
|
||||||
const mesText = getRegexedString(text.trim(), regex_placement.SLASH_COMMAND);
|
const mesText = getRegexedString(text.trim(), regex_placement.SLASH_COMMAND);
|
||||||
// Sending a message implicitly saves the chat, so this needs to be done before changing the character
|
// Sending a message implicitly saves the chat, so this needs to be done before changing the character
|
||||||
@ -2588,19 +2587,9 @@ async function askCharacter(args, text) {
|
|||||||
// Override character and send a user message
|
// Override character and send a user message
|
||||||
setCharacterId(String(chId));
|
setCharacterId(String(chId));
|
||||||
|
|
||||||
const character = characters[chId];
|
const { name, force_avatar, original_avatar } = getNameAndAvatarForMessage(character, args?.name);
|
||||||
let force_avatar, original_avatar;
|
|
||||||
|
|
||||||
if (character && character.avatar !== 'none') {
|
setCharacterName(name);
|
||||||
force_avatar = getThumbnailUrl('avatar', character.avatar);
|
|
||||||
original_avatar = character.avatar;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
force_avatar = default_avatar;
|
|
||||||
original_avatar = default_avatar;
|
|
||||||
}
|
|
||||||
|
|
||||||
setCharacterName(character.name);
|
|
||||||
|
|
||||||
const restoreCharacter = () => {
|
const restoreCharacter = () => {
|
||||||
if (String(this_chid) !== String(chId)) {
|
if (String(this_chid) !== String(chId)) {
|
||||||
@ -2613,7 +2602,7 @@ async function askCharacter(args, text) {
|
|||||||
// Only force the new avatar if the character name is the same
|
// Only force the new avatar if the character name is the same
|
||||||
// This skips if an error was fired
|
// This skips if an error was fired
|
||||||
const lastMessage = chat[chat.length - 1];
|
const lastMessage = chat[chat.length - 1];
|
||||||
if (lastMessage && lastMessage?.name === character.name) {
|
if (lastMessage && lastMessage?.name === name) {
|
||||||
lastMessage.force_avatar = force_avatar;
|
lastMessage.force_avatar = force_avatar;
|
||||||
lastMessage.original_avatar = original_avatar;
|
lastMessage.original_avatar = original_avatar;
|
||||||
}
|
}
|
||||||
@ -2624,7 +2613,7 @@ async function askCharacter(args, text) {
|
|||||||
// Run generate and restore previous character
|
// Run generate and restore previous character
|
||||||
try {
|
try {
|
||||||
eventSource.once(event_types.MESSAGE_RECEIVED, restoreCharacter);
|
eventSource.once(event_types.MESSAGE_RECEIVED, restoreCharacter);
|
||||||
toastr.info(`Asking ${character.name} something...`);
|
toastr.info(`Asking ${name} something...`);
|
||||||
askResult = await Generate('ask_command');
|
askResult = await Generate('ask_command');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
restoreCharacter();
|
restoreCharacter();
|
||||||
@ -3215,6 +3204,41 @@ export function validateArrayArg(arg, name, { allowUndefined = true } = {}) {
|
|||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the name and avatar information for a message
|
||||||
|
*
|
||||||
|
* The name of the character will always have precendence over the one given as argument. If you want to specify a different name for the message,
|
||||||
|
* explicitly implement this in the code using this.
|
||||||
|
*
|
||||||
|
* @param {object?} character - The character object to get the avatar data for
|
||||||
|
* @param {string?} name - The name to get the avatar data for
|
||||||
|
* @returns {{name: string, force_avatar: string, original_avatar: string}} An object containing the name for the message, forced avatar URL, and original avatar
|
||||||
|
*/
|
||||||
|
export function getNameAndAvatarForMessage(character, name = null) {
|
||||||
|
const isNeutralCharacter = !character && name2 === neutralCharacterName && name === neutralCharacterName;
|
||||||
|
const currentChar = characters[this_chid];
|
||||||
|
|
||||||
|
let force_avatar, original_avatar;
|
||||||
|
if (character?.avatar === currentChar?.avatar || isNeutralCharacter) {
|
||||||
|
// If the targeted character is the currently selected one in a solo chat, we don't need to force any avatars
|
||||||
|
}
|
||||||
|
else if (character && character.avatar !== 'none') {
|
||||||
|
force_avatar = getThumbnailUrl('avatar', character.avatar);
|
||||||
|
original_avatar = character.avatar;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
force_avatar = default_avatar;
|
||||||
|
original_avatar = default_avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: character?.name || name,
|
||||||
|
force_avatar: force_avatar,
|
||||||
|
original_avatar: original_avatar,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds a character by name, with optional filtering and precedence for avatars
|
* Finds a character by name, with optional filtering and precedence for avatars
|
||||||
* @param {object} [options={}] - The options for the search
|
* @param {object} [options={}] - The options for the search
|
||||||
@ -3273,6 +3297,19 @@ export function findChar({ name = null, allowAvatar = true, insensitive = true,
|
|||||||
return matchingCharacters[0] || null;
|
return matchingCharacters[0] || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the index of a character based on the character object
|
||||||
|
* @param {object} char - The character object to find the index for
|
||||||
|
* @throws {Error} If the character is not found
|
||||||
|
* @returns {number} The index of the character in the characters array
|
||||||
|
*/
|
||||||
|
export function getCharIndex(char) {
|
||||||
|
if (!char) throw new Error('Character is undefined');
|
||||||
|
const index = characters.findIndex(c => c.avatar === char.avatar);
|
||||||
|
if (index === -1) throw new Error(`Character not found: ${char.avatar}`);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
export async function sendMessageAs(args, text) {
|
export async function sendMessageAs(args, text) {
|
||||||
if (!text) {
|
if (!text) {
|
||||||
return '';
|
return '';
|
||||||
@ -3319,23 +3356,10 @@ export async function sendMessageAs(args, text) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const isNeutralCharacter = !character && name2 === neutralCharacterName && name === neutralCharacterName;
|
const { name: nameForMessage, force_avatar, original_avatar } = getNameAndAvatarForMessage(avatarCharacter, name);
|
||||||
|
|
||||||
let force_avatar, original_avatar;
|
|
||||||
if (character === avatarCharacter || isNeutralCharacter) {
|
|
||||||
// If the targeted character is the currently selected one in a solo chat, we don't need to force any avatars
|
|
||||||
}
|
|
||||||
else if (avatarCharacter && avatarCharacter.avatar !== 'none') {
|
|
||||||
force_avatar = getThumbnailUrl('avatar', avatarCharacter.avatar);
|
|
||||||
original_avatar = avatarCharacter.avatar;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
force_avatar = default_avatar;
|
|
||||||
original_avatar = default_avatar;
|
|
||||||
}
|
|
||||||
|
|
||||||
const message = {
|
const message = {
|
||||||
name: character?.name || name,
|
name: nameForMessage,
|
||||||
is_user: false,
|
is_user: false,
|
||||||
is_system: isSystem,
|
is_system: isSystem,
|
||||||
send_date: getMessageTimeStamp(),
|
send_date: getMessageTimeStamp(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user