mirror of
				https://github.com/SillyTavern/SillyTavern.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	Add /extension-toggle
This commit is contained in:
		| @@ -8,7 +8,7 @@ import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCom | |||||||
| import { enumTypes, SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js'; | import { enumTypes, SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js'; | ||||||
| import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; | ||||||
| import { renderTemplate, renderTemplateAsync } from './templates.js'; | import { renderTemplate, renderTemplateAsync } from './templates.js'; | ||||||
| import { equalsIgnoreCaseAndAccents, isSubsetOf, isTrueBoolean, setValueByPath } from './utils.js'; | import { equalsIgnoreCaseAndAccents, isFalseBoolean, isSubsetOf, isTrueBoolean, setValueByPath } from './utils.js'; | ||||||
| export { | export { | ||||||
|     getContext, |     getContext, | ||||||
|     getApiUrl, |     getApiUrl, | ||||||
| @@ -1050,33 +1050,50 @@ export async function openThirdPartyExtensionMenu(suggestUrl = '') { | |||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @param {boolean} enable - Whether to enable or disable the extension |  * @param {'enable' | 'disable' | 'toggle'} action - The action to perform on the extension | ||||||
|  * @returns {(args: {[key: string]: string | SlashCommandClosure}, extensionName: string | SlashCommandClosure) => Promise<string>} |  * @returns {(args: {[key: string]: string | SlashCommandClosure}, extensionName: string | SlashCommandClosure) => Promise<string>} | ||||||
|  */ |  */ | ||||||
| function getExtensionToggleCallback(enable) { | function getExtensionActionCallback(action) { | ||||||
|     return async (args, extensionName) => { |     return async (args, extensionName) => { | ||||||
|         if (args?.reload instanceof SlashCommandClosure) throw new Error('\'reload\' argument cannot be a closure.'); |         if (args?.reload instanceof SlashCommandClosure) throw new Error('\'reload\' argument cannot be a closure.'); | ||||||
|         if (typeof extensionName !== 'string') throw new Error('Extension name does only support string. Closures or arrays are not allowed.'); |         if (typeof extensionName !== 'string') throw new Error('Extension name does only support string. Closures or arrays are not allowed.'); | ||||||
|         if (!extensionName) { |         if (!extensionName) { | ||||||
|             toastr.warning(`Extension name must be provided as an argument to ${enable ? 'enable' : 'disable'} this extension.`); |             toastr.warning(`Extension name must be provided as an argument to ${action} this extension.`); | ||||||
|             return ''; |             return ''; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         const reload = isTrueBoolean(args?.reload); |         const reload = isTrueBoolean(args?.reload); | ||||||
|  |  | ||||||
|         const internalExtensionName = extensionNames.find(x => equalsIgnoreCaseAndAccents(x, extensionName)); |         const internalExtensionName = extensionNames.find(x => equalsIgnoreCaseAndAccents(x, extensionName)); | ||||||
|         if (!internalExtensionName) { |         if (!internalExtensionName) { | ||||||
|             toastr.warning(`Extension ${extensionName} does not exist.`); |             toastr.warning(`Extension ${extensionName} does not exist.`); | ||||||
|             return ''; |             return ''; | ||||||
|         } |         } | ||||||
|         if (enable === !extension_settings.disabledExtensions.includes(internalExtensionName)) { |  | ||||||
|             toastr.info(`Extension ${extensionName} is already ${enable ? 'enabled' : 'disabled'}.`); |         const isEnabled = !extension_settings.disabledExtensions.includes(internalExtensionName); | ||||||
|  |  | ||||||
|  |         if (action === 'enable' && isEnabled) { | ||||||
|  |             toastr.info(`Extension ${extensionName} is already enabled.`); | ||||||
|             return internalExtensionName; |             return internalExtensionName; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         reload && toastr.info(`${enable ? 'Enabling' : 'Disabling'} extension ${extensionName} and reloading...`); |         if (action === 'disable' && !isEnabled) { | ||||||
|         await enableExtension(internalExtensionName, reload); |             toastr.info(`Extension ${extensionName} is already disabled.`); | ||||||
|         toastr.success(`Extension ${extensionName} ${enable ? 'enabled' : 'disabled'}.`); |             return internalExtensionName; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (action === 'toggle') { | ||||||
|  |             action = isEnabled ? 'disable' : 'enable'; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         reload && toastr.info(`${action.charAt(0).toUpperCase() + action.slice(1)}ing extension ${extensionName} and reloading...`); | ||||||
|  |  | ||||||
|  |         if (action === 'enable') { | ||||||
|  |             await enableExtension(internalExtensionName, reload); | ||||||
|  |         } else { | ||||||
|  |             await disableExtension(internalExtensionName, reload); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         toastr.success(`Extension ${extensionName} ${action}d.`); | ||||||
|  |  | ||||||
|         return internalExtensionName; |         return internalExtensionName; | ||||||
|     }; |     }; | ||||||
| @@ -1085,7 +1102,7 @@ function getExtensionToggleCallback(enable) { | |||||||
| function registerExtensionSlashCommands() { | function registerExtensionSlashCommands() { | ||||||
|     SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |     SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | ||||||
|         name: 'extension-enable', |         name: 'extension-enable', | ||||||
|         callback: getExtensionToggleCallback(true), |         callback: getExtensionActionCallback('enable'), | ||||||
|         namedArgumentList: [ |         namedArgumentList: [ | ||||||
|             SlashCommandNamedArgument.fromProps({ |             SlashCommandNamedArgument.fromProps({ | ||||||
|                 name: 'reload', |                 name: 'reload', | ||||||
| @@ -1125,7 +1142,7 @@ function registerExtensionSlashCommands() { | |||||||
|     })); |     })); | ||||||
|     SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |     SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | ||||||
|         name: 'extension-disable', |         name: 'extension-disable', | ||||||
|         callback: getExtensionToggleCallback(false), |         callback: getExtensionActionCallback('enable'), | ||||||
|         namedArgumentList: [ |         namedArgumentList: [ | ||||||
|             SlashCommandNamedArgument.fromProps({ |             SlashCommandNamedArgument.fromProps({ | ||||||
|                 name: 'reload', |                 name: 'reload', | ||||||
| @@ -1163,6 +1180,64 @@ function registerExtensionSlashCommands() { | |||||||
|             </div> |             </div> | ||||||
|         `, |         `, | ||||||
|     })); |     })); | ||||||
|  |     SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | ||||||
|  |         name: 'extension-toggle', | ||||||
|  |         callback: async (args, extensionName) => { | ||||||
|  |             if (args?.state instanceof SlashCommandClosure) throw new Error('\'state\' argument cannot be a closure.'); | ||||||
|  |             if (typeof extensionName !== 'string') throw new Error('Extension name does only support string. Closures or arrays are not allowed.'); | ||||||
|  |  | ||||||
|  |             const action = isTrueBoolean(args?.state) ? 'enable' : | ||||||
|  |                 isFalseBoolean(args?.state) ? 'disable' : | ||||||
|  |                     'toggle'; | ||||||
|  |  | ||||||
|  |             return await getExtensionActionCallback(action)(args, extensionName); | ||||||
|  |         }, | ||||||
|  |         namedArgumentList: [ | ||||||
|  |             SlashCommandNamedArgument.fromProps({ | ||||||
|  |                 name: 'reload', | ||||||
|  |                 description: 'Whether to reload the page after toggling the extension', | ||||||
|  |                 typeList: [ARGUMENT_TYPE.BOOLEAN], | ||||||
|  |                 defaultValue: 'true', | ||||||
|  |                 enumList: commonEnumProviders.boolean('trueFalse')(), | ||||||
|  |             }), | ||||||
|  |             SlashCommandNamedArgument.fromProps({ | ||||||
|  |                 name: 'state', | ||||||
|  |                 description: 'Explicitly set the state of the extension (true to enable, false to disable). If not provided, the state will be toggled to the opposite of the current state.', | ||||||
|  |                 typeList: [ARGUMENT_TYPE.BOOLEAN], | ||||||
|  |                 enumList: commonEnumProviders.boolean('trueFalse')(), | ||||||
|  |             }), | ||||||
|  |         ], | ||||||
|  |         unnamedArgumentList: [ | ||||||
|  |             SlashCommandArgument.fromProps({ | ||||||
|  |                 description: 'Extension name', | ||||||
|  |                 typeList: [ARGUMENT_TYPE.STRING], | ||||||
|  |                 isRequired: true, | ||||||
|  |                 enumProvider: () => extensionNames.map(name => new SlashCommandEnumValue(name)), | ||||||
|  |                 forceEnum: true, | ||||||
|  |             }), | ||||||
|  |         ], | ||||||
|  |         helpString: ` | ||||||
|  |             <div> | ||||||
|  |                 Toggles the state of a specified extension. | ||||||
|  |             </div> | ||||||
|  |             <div> | ||||||
|  |                 By default, the page will be reloaded automatically, stopping any further commands.<br /> | ||||||
|  |                 If <code>reload=false</code> named argument is passed, the page will not be reloaded, and the extension will stay in its current state until refreshed. | ||||||
|  |                 The page either needs to be refreshed, or <code>/reload-page</code> has to be called. | ||||||
|  |             </div> | ||||||
|  |             <div> | ||||||
|  |                 <strong>Example:</strong> | ||||||
|  |                 <ul> | ||||||
|  |                     <li> | ||||||
|  |                         <pre><code class="language-stscript">/extension-toggle Summarize</code></pre> | ||||||
|  |                     </li> | ||||||
|  |                     <li> | ||||||
|  |                         <pre><code class="language-stscript">/extension-toggle Summarize state=true</code></pre> | ||||||
|  |                     </li> | ||||||
|  |                 </ul> | ||||||
|  |             </div> | ||||||
|  |         `, | ||||||
|  |     })); | ||||||
|  |  | ||||||
|     SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |     SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | ||||||
|         name: 'reload-page', |         name: 'reload-page', | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user