mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Add "name" argument to /hide and /unhide. Add default value for unnamed argument
This commit is contained in:
@ -130,9 +130,10 @@ function getConverter(type) {
|
|||||||
* @param {number} start Starting message ID
|
* @param {number} start Starting message ID
|
||||||
* @param {number} end Ending message ID (inclusive)
|
* @param {number} end Ending message ID (inclusive)
|
||||||
* @param {boolean} unhide If true, unhide the messages instead.
|
* @param {boolean} unhide If true, unhide the messages instead.
|
||||||
|
* @param {string} nameFitler Optional name filter
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
export async function hideChatMessageRange(start, end, unhide) {
|
export async function hideChatMessageRange(start, end, unhide, nameFitler = null) {
|
||||||
if (isNaN(start)) return;
|
if (isNaN(start)) return;
|
||||||
if (!end) end = start;
|
if (!end) end = start;
|
||||||
const hide = !unhide;
|
const hide = !unhide;
|
||||||
@ -140,6 +141,7 @@ export async function hideChatMessageRange(start, end, unhide) {
|
|||||||
for (let messageId = start; messageId <= end; messageId++) {
|
for (let messageId = start; messageId <= end; messageId++) {
|
||||||
const message = chat[messageId];
|
const message = chat[messageId];
|
||||||
if (!message) continue;
|
if (!message) continue;
|
||||||
|
if (nameFitler && message.name !== nameFitler) continue;
|
||||||
|
|
||||||
message.is_system = hide;
|
message.is_system = hide;
|
||||||
|
|
||||||
|
@ -667,11 +667,21 @@ export function initDefaultSlashCommands() {
|
|||||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||||
name: 'hide',
|
name: 'hide',
|
||||||
callback: hideMessageCallback,
|
callback: hideMessageCallback,
|
||||||
|
namedArgumentList: [
|
||||||
|
SlashCommandNamedArgument.fromProps({
|
||||||
|
name: 'name',
|
||||||
|
description: 'only hide messages from a certain character or persona',
|
||||||
|
typeList: [ARGUMENT_TYPE.STRING],
|
||||||
|
enumProvider: commonEnumProviders.messageNames,
|
||||||
|
isRequired: false,
|
||||||
|
acceptsMultiple: false,
|
||||||
|
}),
|
||||||
|
],
|
||||||
unnamedArgumentList: [
|
unnamedArgumentList: [
|
||||||
SlashCommandArgument.fromProps({
|
SlashCommandArgument.fromProps({
|
||||||
description: 'message index (starts with 0) or range',
|
description: 'message index (starts with 0) or range, defaults to the last message index if not provided',
|
||||||
typeList: [ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.RANGE],
|
typeList: [ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.RANGE],
|
||||||
isRequired: true,
|
isRequired: false,
|
||||||
enumProvider: commonEnumProviders.messages(),
|
enumProvider: commonEnumProviders.messages(),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@ -680,11 +690,21 @@ export function initDefaultSlashCommands() {
|
|||||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||||
name: 'unhide',
|
name: 'unhide',
|
||||||
callback: unhideMessageCallback,
|
callback: unhideMessageCallback,
|
||||||
|
namedArgumentList: [
|
||||||
|
SlashCommandNamedArgument.fromProps({
|
||||||
|
name: 'name',
|
||||||
|
description: 'only unhide messages from a certain character or persona',
|
||||||
|
typeList: [ARGUMENT_TYPE.STRING],
|
||||||
|
enumProvider: commonEnumProviders.messageNames,
|
||||||
|
isRequired: false,
|
||||||
|
acceptsMultiple: false,
|
||||||
|
}),
|
||||||
|
],
|
||||||
unnamedArgumentList: [
|
unnamedArgumentList: [
|
||||||
SlashCommandArgument.fromProps({
|
SlashCommandArgument.fromProps({
|
||||||
description: 'message index (starts with 0) or range',
|
description: 'message index (starts with 0) or range, defaults to the last message index if not provided',
|
||||||
typeList: [ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.RANGE],
|
typeList: [ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.RANGE],
|
||||||
isRequired: true,
|
isRequired: false,
|
||||||
enumProvider: commonEnumProviders.messages(),
|
enumProvider: commonEnumProviders.messages(),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@ -3034,37 +3054,37 @@ async function askCharacter(args, text) {
|
|||||||
return await slashCommandReturnHelper.doReturn(args.return ?? 'pipe', message, { objectToStringFunc: x => x.mes });
|
return await slashCommandReturnHelper.doReturn(args.return ?? 'pipe', message, { objectToStringFunc: x => x.mes });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function hideMessageCallback(_, arg) {
|
async function hideMessageCallback(args, value) {
|
||||||
if (!arg) {
|
if (!value) {
|
||||||
console.warn('WARN: No argument provided for /hide command');
|
console.log('No range provided. Hiding the last message.');
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const range = stringToRange(arg, 0, chat.length - 1);
|
const range = value ? stringToRange(value, 0, chat.length - 1) : { start: chat.length - 1, end: chat.length - 1 };
|
||||||
|
|
||||||
if (!range) {
|
if (!range) {
|
||||||
console.warn(`WARN: Invalid range provided for /hide command: ${arg}`);
|
console.warn(`WARN: Invalid range provided for /hide command: ${value}`);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
await hideChatMessageRange(range.start, range.end, false);
|
const nameFilter = String(args.name ?? '').trim();
|
||||||
|
await hideChatMessageRange(range.start, range.end, false, nameFilter);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function unhideMessageCallback(_, arg) {
|
async function unhideMessageCallback(args, value) {
|
||||||
if (!arg) {
|
if (!value) {
|
||||||
console.warn('WARN: No argument provided for /unhide command');
|
console.log('No range provided. Unhiding the last message');
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const range = stringToRange(arg, 0, chat.length - 1);
|
const range = value ? stringToRange(value, 0, chat.length - 1) : { start: chat.length - 1, end: chat.length - 1 };
|
||||||
|
|
||||||
if (!range) {
|
if (!range) {
|
||||||
console.warn(`WARN: Invalid range provided for /unhide command: ${arg}`);
|
console.warn(`WARN: Invalid range provided for /unhide command: ${value}`);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
await hideChatMessageRange(range.start, range.end, true);
|
const nameFilter = String(args.name ?? '').trim();
|
||||||
|
await hideChatMessageRange(range.start, range.end, true, nameFilter);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { extension_settings } from '../extensions.js';
|
|||||||
import { getGroupMembers, groups } from '../group-chats.js';
|
import { getGroupMembers, groups } from '../group-chats.js';
|
||||||
import { power_user } from '../power-user.js';
|
import { power_user } from '../power-user.js';
|
||||||
import { searchCharByName, getTagsList, tags, tag_map } from '../tags.js';
|
import { searchCharByName, getTagsList, tags, tag_map } from '../tags.js';
|
||||||
|
import { onlyUnique } from '../utils.js';
|
||||||
import { world_names } from '../world-info.js';
|
import { world_names } from '../world-info.js';
|
||||||
import { SlashCommandClosure } from './SlashCommandClosure.js';
|
import { SlashCommandClosure } from './SlashCommandClosure.js';
|
||||||
import { SlashCommandEnumValue, enumTypes } from './SlashCommandEnumValue.js';
|
import { SlashCommandEnumValue, enumTypes } from './SlashCommandEnumValue.js';
|
||||||
@ -251,14 +252,22 @@ export const commonEnumProviders = {
|
|||||||
* @param {boolean} [options.allowVars=false] - Whether to add enum option for variable names
|
* @param {boolean} [options.allowVars=false] - Whether to add enum option for variable names
|
||||||
* @returns {(executor:SlashCommandExecutor, scope:SlashCommandScope) => SlashCommandEnumValue[]}
|
* @returns {(executor:SlashCommandExecutor, scope:SlashCommandScope) => SlashCommandEnumValue[]}
|
||||||
*/
|
*/
|
||||||
messages: ({ allowIdAfter = false, allowVars = false } = {}) => (_, scope) => {
|
messages: ({ allowIdAfter = false, allowVars = false } = {}) => (executor, scope) => {
|
||||||
|
const nameFilter = executor.namedArgumentList.find(it => it.name == 'name')?.value || '';
|
||||||
return [
|
return [
|
||||||
...chat.map((message, index) => new SlashCommandEnumValue(String(index), `${message.name}: ${message.mes}`, enumTypes.number, message.is_user ? enumIcons.user : message.is_system ? enumIcons.system : enumIcons.assistant)),
|
...chat.map((message, index) => new SlashCommandEnumValue(String(index), `${message.name}: ${message.mes}`, enumTypes.number, message.is_user ? enumIcons.user : message.is_system ? enumIcons.system : enumIcons.assistant)).filter(value => !nameFilter || value.description.startsWith(`${nameFilter}:`)),
|
||||||
...allowIdAfter ? [new SlashCommandEnumValue(String(chat.length), '>> After Last Message >>', enumTypes.enum, '➕')] : [],
|
...allowIdAfter ? [new SlashCommandEnumValue(String(chat.length), '>> After Last Message >>', enumTypes.enum, '➕')] : [],
|
||||||
...allowVars ? commonEnumProviders.variables('all')(_, scope) : [],
|
...allowVars ? commonEnumProviders.variables('all')(executor, scope) : [],
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All names used in the current chat.
|
||||||
|
*
|
||||||
|
* @returns {SlashCommandEnumValue[]}
|
||||||
|
*/
|
||||||
|
messageNames: () => chat.map((message) => message.name).filter(onlyUnique).sort(Intl.Collator().compare).map(name => new SlashCommandEnumValue(name)),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All existing worlds / lorebooks
|
* All existing worlds / lorebooks
|
||||||
*
|
*
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
} from '../lib.js';
|
} from '../lib.js';
|
||||||
|
|
||||||
import { getContext } from './extensions.js';
|
import { getContext } from './extensions.js';
|
||||||
import { characters, getRequestHeaders, this_chid } from '../script.js';
|
import { characters, getRequestHeaders, this_chid, user_avatar } from '../script.js';
|
||||||
import { isMobile } from './RossAscends-mods.js';
|
import { isMobile } from './RossAscends-mods.js';
|
||||||
import { collapseNewlines, power_user } from './power-user.js';
|
import { collapseNewlines, power_user } from './power-user.js';
|
||||||
import { debounce_timeout } from './constants.js';
|
import { debounce_timeout } from './constants.js';
|
||||||
@ -2196,6 +2196,48 @@ export async function showFontAwesomePicker(customList = null) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a persona by name, with optional filtering and precedence for avatars
|
||||||
|
* @param {object} [options={}] - The options for the search
|
||||||
|
* @param {string?} [options.name=null] - The name to search for
|
||||||
|
* @param {boolean} [options.allowAvatar=true] - Whether to allow searching by avatar
|
||||||
|
* @param {boolean} [options.insensitive=true] - Whether the search should be case insensitive
|
||||||
|
* @param {boolean} [options.preferCurrentPersona=true] - Whether to prefer the current persona(s)
|
||||||
|
* @param {boolean} [options.quiet=false] - Whether to suppress warnings
|
||||||
|
* @returns {PersonaViewModel} The persona object
|
||||||
|
* @typedef {object} PersonaViewModel
|
||||||
|
* @property {string} avatar - The avatar of the persona
|
||||||
|
* @property {string} name - The name of the persona
|
||||||
|
*/
|
||||||
|
export function findPersona({ name = null, allowAvatar = true, insensitive = true, preferCurrentPersona = true, quiet = false } = {}) {
|
||||||
|
/** @type {PersonaViewModel[]} */
|
||||||
|
const personas = Object.entries(power_user.personas).map(([avatar, name]) => ({ avatar, name }));
|
||||||
|
const matches = (/** @type {PersonaViewModel} */ persona) => !name || (allowAvatar && persona.avatar === name) || (insensitive ? equalsIgnoreCaseAndAccents(persona.name, name) : persona.name === name);
|
||||||
|
|
||||||
|
// If we have a current persona and prefer it, return that if it matches
|
||||||
|
const currentPersona = personas.find(a => a.avatar === user_avatar);
|
||||||
|
if (preferCurrentPersona && currentPersona && matches(currentPersona)) {
|
||||||
|
return currentPersona;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If allowAvatar is true, search by avatar first
|
||||||
|
if (allowAvatar && name) {
|
||||||
|
const personaByAvatar = personas.find(a => a.avatar === name);
|
||||||
|
if (personaByAvatar && matches(personaByAvatar)) {
|
||||||
|
return personaByAvatar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for matching personas by name
|
||||||
|
const matchingPersonas = personas.filter(a => matches(a));
|
||||||
|
if (matchingPersonas.length > 1) {
|
||||||
|
if (!quiet) toastr.warning('Multiple personas found for given conditions.');
|
||||||
|
else console.warn('Multiple personas found for given conditions. Returning the first match.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchingPersonas[0] || null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
Reference in New Issue
Block a user