Allow searching on /sendas via tag=
This commit is contained in:
parent
4594353c72
commit
22d8a654d9
|
@ -187,10 +187,17 @@ export function initDefaultSlashCommands() {
|
|||
}),
|
||||
SlashCommandNamedArgument.fromProps({
|
||||
name: 'avatar',
|
||||
description: 'Optional 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 filename or just the character name to pull the avatar from)',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
enumProvider: commonEnumProviders.characters('character'),
|
||||
}),
|
||||
SlashCommandNamedArgument.fromProps({
|
||||
name: 'tag',
|
||||
description: 'Supply one or more tags to filter down to the correct character for the provided name, if multiple characters have the same name. (does not apply to the avatar argument)',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
enumProvider: commonEnumProviders.tagsForChar('all'),
|
||||
acceptsMultiple: true,
|
||||
}),
|
||||
SlashCommandNamedArgument.fromProps({
|
||||
name: 'compact',
|
||||
description: 'Use compact layout',
|
||||
|
@ -3109,6 +3116,44 @@ async function setNarratorName(_, text) {
|
|||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a character by name, with optional filtering and precedence for avatars
|
||||
* @param {string} name - The name to search for
|
||||
* @param {object} [options={}] - The options for the search
|
||||
* @param {boolean} [options.allowAvatar=false] - Whether to allow searching by avatar
|
||||
* @param {boolean} [options.insensitive=true] - Whether the search should be case insensitive
|
||||
* @param {string[]?} [options.filteredByTags=null] - Tags to filter characters by
|
||||
* @param {any?} [options.preferCurrentChar=null] - The current character to prefer
|
||||
* @returns {any?} - The found character or null if not found
|
||||
*/
|
||||
export function findCharByName(name, { allowAvatar = false, insensitive = true, filteredByTags = null, preferCurrentChar = null } = {}) {
|
||||
const matches = (char) => (allowAvatar && char.avatar === name) || insensitive ? equalsIgnoreCaseAndAccents(char.name, name) : char.name === name;
|
||||
|
||||
// If we have a current char and prefer it, return that if it matches - unless tags are provided, they have precedence
|
||||
if (preferCurrentChar && !filteredByTags && matches(preferCurrentChar)) {
|
||||
return preferCurrentChar;
|
||||
}
|
||||
|
||||
// Filter characters by tags if provided
|
||||
let filteredCharacters = characters;
|
||||
if (filteredByTags) {
|
||||
filteredCharacters = characters.filter(char => filteredByTags.every(tag => char.tags.includes(tag)));
|
||||
}
|
||||
|
||||
// If allowAvatar is true, search by avatar first
|
||||
if (allowAvatar) {
|
||||
const characterByAvatar = filteredCharacters.find(char => char.avatar === name);
|
||||
if (characterByAvatar) {
|
||||
return characterByAvatar;
|
||||
}
|
||||
}
|
||||
|
||||
// Search for a matching character by name
|
||||
let character = filteredCharacters.find(matches);
|
||||
|
||||
return character;
|
||||
}
|
||||
|
||||
export async function sendMessageAs(args, text) {
|
||||
if (!text) {
|
||||
return '';
|
||||
|
@ -3150,24 +3195,21 @@ export async function sendMessageAs(args, text) {
|
|||
const chatCharacter = this_chid !== undefined ? characters[this_chid] : null;
|
||||
const isNeutralCharacter = !chatCharacter && name2 === neutralCharacterName && name === neutralCharacterName;
|
||||
|
||||
const character = equalsIgnoreCaseAndAccents(chatCharacter.name, name) ? chatCharacter : characters.find(x => equalsIgnoreCaseAndAccents(x.name, name));
|
||||
const character = findCharByName(name, { filteredByTags: args?.tags, preferCurrentChar: chatCharacter });
|
||||
|
||||
let avatarChar = character;
|
||||
if (args.avatar) {
|
||||
avatarChar = characters.find(x => x.avatar == args.avatar) ?? characters.find(x => equalsIgnoreCaseAndAccents(x.name, args.avatar));
|
||||
if (!avatarChar) {
|
||||
const avatarCharacter = args.avatar ? findCharByName(args.avatar) : character;
|
||||
if (args.avatar && !avatarCharacter) {
|
||||
toastr.warning(`Character for avatar ${args.avatar} not found`);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
let force_avatar, original_avatar;
|
||||
if (chatCharacter === avatarChar || isNeutralCharacter) {
|
||||
if (chatCharacter === 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 (avatarChar && avatarChar.avatar !== 'none') {
|
||||
force_avatar = getThumbnailUrl('avatar', avatarChar.avatar);
|
||||
original_avatar = avatarChar.avatar;
|
||||
else if (avatarCharacter && avatarCharacter.avatar !== 'none') {
|
||||
force_avatar = getThumbnailUrl('avatar', avatarCharacter.avatar);
|
||||
original_avatar = avatarCharacter.avatar;
|
||||
}
|
||||
else {
|
||||
force_avatar = default_avatar;
|
||||
|
|
|
@ -193,7 +193,7 @@ export const commonEnumProviders = {
|
|||
if (charName instanceof SlashCommandClosure) throw new Error('Argument \'name\' does not support closures');
|
||||
const key = searchCharByName(substituteParams(charName), { suppressLogging: true });
|
||||
const assigned = key ? getTagsList(key) : [];
|
||||
return tags.filter(it => !key || mode === 'all' || mode === 'existing' && assigned.includes(it) || mode === 'not-existing' && !assigned.includes(it))
|
||||
return tags.filter(it => mode === 'all' || mode === 'existing' && assigned.includes(it) || mode === 'not-existing' && !assigned.includes(it))
|
||||
.map(tag => new SlashCommandEnumValue(tag.name, null, enumTypes.command, enumIcons.tag));
|
||||
},
|
||||
|
||||
|
|
Loading…
Reference in New Issue