Refactor findChar to utils - Refactor and move finChar to utils, instead of slashcommands function - Refactor scrapers to use actual init functionality

d7bad6335c34744a7c58875c1d075d61f69cc333

Wolfsblvt <wolfsblvt@gmail.com>

6 files changed, +94 -110Ignore whitespace
public/script.js+2 -1
@@ -230,7 +230,7 @@ import { MacrosParser, evaluateMacros, getLastMessageId } from './scripts/macros
230230import { currentUser, setUserControls } from './scripts/user.js';
231231import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup, fixToastrForDialogs } from './scripts/popup.js';
232232import { renderTemplate, renderTemplateAsync } from './scripts/templates.js';
233233import { initScrapers, ScraperManager } from './scripts/scrapers.js';
234234import { SlashCommandParser } from './scripts/slash-commands/SlashCommandParser.js';
235235import { SlashCommand } from './scripts/slash-commands/SlashCommand.js';
236236import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './scripts/slash-commands/SlashCommandArgument.js';
@@ -959,6 +959,7 @@ async function firstLoadInit() {
959959 initCfg();
960960 initLogprobs();
961961 initInputMarkdown();
962+ initScrapers();
962963 doDailyExtensionUpdatesCheck();
963964 await hideLoader();
964965 await fixViewport();
public/scripts/extensions/expressions/index.js+1 -2
@@ -2,7 +2,7 @@ import { callPopup, eventSource, event_types, generateRaw, getRequestHeaders, ma
22import { dragElement, isMobile } from '../../RossAscends-mods.js';
33import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch, renderExtensionTemplateAsync } from '../../extensions.js';
44import { loadMovingUIState, power_user } from '../../power-user.js';
55import { onlyUnique, debounce, getCharaFilename, trimToEndSentence, trimToStartSentence, waitUntilCondition, findChar } from '../../utils.js';
66import { hideMutedSprites } from '../../group-chats.js';
77import { isJsonSchemaSupported } from '../../textgen-settings.js';
88import { debounce_timeout } from '../../constants.js';
@@ -12,7 +12,6 @@ import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '
1212import { isFunctionCallingSupported } from '../../openai.js';
1313import { SlashCommandEnumValue, enumTypes } from '../../slash-commands/SlashCommandEnumValue.js';
1414import { commonEnumProviders } from '../../slash-commands/SlashCommandCommonEnumsProvider.js';
15-import { findChar } from '../../slash-commands.js';
1615export { MODULE_NAME };
1716
1817const MODULE_NAME = 'expressions';
public/scripts/scrapers.js+15 -6
@@ -13,6 +13,7 @@ import { isValidUrl } from './utils.js';
1313 * @property {string} description
1414 * @property {string} iconClass
1515 * @property {boolean} iconAvailable
16+ * @property {() => Promise<void>} [init=null]
1617 * @property {() => Promise<boolean>} isAvailable
1718 * @property {() => Promise<File[]>} scrape
1819 */
@@ -42,6 +43,10 @@ export class ScraperManager {
4243 return;
4344 }
4445
46+ if (scraper.init) {
47+ scraper.init();
48+ }
49+
4550 ScraperManager.#scrapers.push(scraper);
4651 }
4752
@@ -462,7 +467,9 @@ class YouTubeScraper {
462467 this.description = 'Download a transcript from a YouTube video.';
463468 this.iconClass = 'fa-brands fa-youtube';
464469 this.iconAvailable = true;
470+ }
465471
472+ async init() {
466473 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
467474 name: 'yt-script',
468475 callback: async (args, url) => {
@@ -564,9 +571,11 @@ class YouTubeScraper {
564571 }
565572}
566573
567-ScraperManager.registerDataBankScraper(new FileScraper());
574+export function initScrapers() {
568575 ScraperManager.registerDataBankScraper(new NotepadFileScraper());
569576 ScraperManager.registerDataBankScraper(new WebScraperNotepad());
570577 ScraperManager.registerDataBankScraper(new MediaWikiScraperWebScraper());
571578 ScraperManager.registerDataBankScraper(new FandomScraperMediaWikiScraper());
572579 ScraperManager.registerDataBankScraper(new YouTubeScraperFandomScraper());
580+ ScraperManager.registerDataBankScraper(new YouTubeScraper());
581+}
public/scripts/slash-commands.js+1 -97
@@ -55,7 +55,7 @@ import { autoSelectPersona, retriggerFirstMessageOnEmptyChat, setPersonaLockStat
5555import { addEphemeralStoppingString, chat_styles, flushEphemeralStoppingStrings, power_user } from './power-user.js';
5656import { SERVER_INPUTS, textgen_types, textgenerationwebui_settings } from './textgen-settings.js';
5757import { decodeTextTokens, getAvailableTokenizers, getFriendlyTokenizerName, getTextTokens, getTokenCountAsync, selectTokenizer } from './tokenizers.js';
5858import { debounce, delay, equalsIgnoreCaseAndAccents, findChar, isFalseBoolean, isTrueBoolean, showFontAwesomePicker, stringToRange, trimToEndSentence, trimToStartSentence, waitUntilCondition } from './utils.js';
5959import { registerVariableCommands, resolveVariable } from './variables.js';
6060import { background_settings } from './backgrounds.js';
6161import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js';
@@ -68,10 +68,8 @@ import { SlashCommandNamedArgumentAssignment } from './slash-commands/SlashComma
6868import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js';
6969import { POPUP_TYPE, Popup, callGenericPopup } from './popup.js';
7070import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';
71-import { SlashCommandDebugController } from './slash-commands/SlashCommandDebugController.js';
7271import { SlashCommandBreakController } from './slash-commands/SlashCommandBreakController.js';
7372import { SlashCommandExecutionError } from './slash-commands/SlashCommandExecutionError.js';
74-import { getTagsList } from './tags.js';
7573export {
7674 executeSlashCommands, executeSlashCommandsWithOptions, getSlashCommandsHelp, registerSlashCommand,
7775};
@@ -2969,29 +2967,6 @@ async function deleteMessagesByNameCallback(_, name) {
29692967 return '';
29702968}
29712969
2972-function findCharacterIndex(name) {
2973- const matchTypes = [
2974- (a, b) => a === b,
2975- (a, b) => a.startsWith(b),
2976- (a, b) => a.includes(b),
2977- ];
2978-
2979- const exactAvatarMatch = characters.findIndex(x => x.avatar === name);
2980-
2981- if (exactAvatarMatch !== -1) {
2982- return exactAvatarMatch;
2983- }
2984-
2985- for (const matchType of matchTypes) {
2986- const index = characters.findIndex(x => matchType(x.name.toLowerCase(), name.toLowerCase()));
2987- if (index !== -1) {
2988- return index;
2989- }
2990- }
2991-
2992- return -1;
2993-}
2994-
29952970async function goToCharacterCallback(_, name) {
29962971 if (!name) {
29972972 console.warn('WARN: No character name provided for /go command');
@@ -3238,77 +3213,6 @@ export function getNameAndAvatarForMessage(character, name = null) {
32383213 };
32393214}
32403215
3241-/**
3242- * Finds a character by name, with optional filtering and precedence for avatars
3243- * @param {object} [options={}] - The options for the search
3244- * @param {string?} [options.name=null] - The name to search for
3245- * @param {boolean} [options.allowAvatar=true] - Whether to allow searching by avatar
3246- * @param {boolean} [options.insensitive=true] - Whether the search should be case insensitive
3247- * @param {string[]?} [options.filteredByTags=null] - Tags to filter characters by
3248- * @param {boolean} [options.preferCurrentChar=true] - Whether to prefer the current character(s)
3249- * @param {boolean} [options.quiet=false] - Whether to suppress warnings
3250- * @returns {any?} - The found character or null if not found
3251- */
3252-export function findChar({ name = null, allowAvatar = true, insensitive = true, filteredByTags = null, preferCurrentChar = true, quiet = false } = {}) {
3253- const matches = (char) => (allowAvatar && char.avatar === name) || (insensitive ? equalsIgnoreCaseAndAccents(char.name, name) : char.name === name);
3254-
3255- // Filter characters by tags if provided
3256- let filteredCharacters = characters;
3257- if (filteredByTags) {
3258- filteredCharacters = characters.filter(char => {
3259- const charTags = getTagsList(char.avatar, false);
3260- return filteredByTags.every(tagName => charTags.some(x => x.name == tagName));
3261- });
3262- }
3263-
3264- // Get the current character(s)
3265- /** @type {any[]} */
3266- const currentChars = selected_group ? groups.find(group => group.id === selected_group)?.members.map(member => filteredCharacters.find(char => char.avatar === member))
3267- : [filteredCharacters.find(char => characters[this_chid]?.avatar === char.avatar)];
3268-
3269- // If we have a current char and prefer it, return that if it matches
3270- if (preferCurrentChar) {
3271- const preferredCharSearch = currentChars.filter(matches);
3272- if (preferredCharSearch.length > 1) {
3273- if (!quiet) toastr.warning(`Multiple characters found for name "${name}" and given conditions.`);
3274- else console.warn(`Multiple characters found for name "${name}". Returning the first match.`);
3275- }
3276- if (preferredCharSearch.length) {
3277- return preferredCharSearch[0];
3278- }
3279- }
3280-
3281- // If allowAvatar is true, search by avatar first
3282- if (allowAvatar && name) {
3283- const characterByAvatar = filteredCharacters.find(char => char.avatar === name);
3284- if (characterByAvatar) {
3285- return characterByAvatar;
3286- }
3287- }
3288-
3289- // Search for matching characters by name
3290- const matchingCharacters = name ? filteredCharacters.filter(matches) : filteredCharacters;
3291- if (matchingCharacters.length > 1) {
3292- if (!quiet) toastr.warning(`Multiple characters found for name "${name}" and given conditions.`);
3293- else console.warn(`Multiple characters found for name "${name}". Returning the first match.`);
3294- }
3295-
3296- return matchingCharacters[0] || null;
3297-}
3298-
3299-/**
3300- * Gets the index of a character based on the character object
3301- * @param {object} char - The character object to find the index for
3302- * @throws {Error} If the character is not found
3303- * @returns {number} The index of the character in the characters array
3304- */
3305-export function getCharIndex(char) {
3306- if (!char) throw new Error('Character is undefined');
3307- const index = characters.findIndex(c => c.avatar === char.avatar);
3308- if (index === -1) throw new Error(`Character not found: ${char.avatar}`);
3309- return index;
3310-}
3311-
33123216export async function sendMessageAs(args, text) {
33133217 if (!text) {
33143218 return '';
public/scripts/tags.js+1 -3
@@ -15,7 +15,7 @@ import {
1515import { FILTER_TYPES, FILTER_STATES, DEFAULT_FILTER_STATE, isFilterState, FilterHelper } from './filters.js';
1616
1717import { groupCandidatesFilter, groups, selected_group } from './group-chats.js';
1818import { download, onlyUnique, parseJsonFile, uuidv4, getSortableDelay, flashHighlight, equalsIgnoreCaseAndAccents, includesIgnoreCaseAndAccents, removeFromArray, getFreeName, debounce, findChar } from './utils.js';
1919import { power_user } from './power-user.js';
2020import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
2121import { SlashCommand } from './slash-commands/SlashCommand.js';
@@ -26,7 +26,6 @@ import { debounce_timeout } from './constants.js';
2626import { INTERACTABLE_CONTROL_CLASS } from './keyboard.js';
2727import { commonEnumProviders } from './slash-commands/SlashCommandCommonEnumsProvider.js';
2828import { renderTemplateAsync } from './templates.js';
29-import { findChar } from './slash-commands.js';
3029
3130export {
3231 TAG_FOLDER_TYPES,
@@ -51,7 +50,6 @@ export {
5150 removeTagFromMap,
5251};
5352
54-/** @typedef {import('../scripts/popup.js').Popup} Popup */
5553/** @typedef {import('../script.js').Character} Character */
5654
5755const CHARACTER_FILTER_SELECTOR = '#rm_characters_block .rm_tag_filter';
public/scripts/utils.js+74 -1
@@ -1,10 +1,12 @@
11import { getContext } from './extensions.js';
22import { characters, getRequestHeaders, this_chid } from '../script.js';
33import { isMobile } from './RossAscends-mods.js';
44import { collapseNewlines } from './power-user.js';
55import { debounce_timeout } from './constants.js';
66import { Popup, POPUP_RESULT, POPUP_TYPE } from './popup.js';
77import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js';
8+import { getTagsList } from './tags.js';
9+import { groups, selected_group } from './group-chats.js';
810
911/**
1012 * Pagination status string template.
@@ -2110,3 +2112,74 @@ export async function showFontAwesomePicker(customList = null) {
21102112 }
21112113 return null;
21122114}
2115+
2116+/**
2117+ * Finds a character by name, with optional filtering and precedence for avatars
2118+ * @param {object} [options={}] - The options for the search
2119+ * @param {string?} [options.name=null] - The name to search for
2120+ * @param {boolean} [options.allowAvatar=true] - Whether to allow searching by avatar
2121+ * @param {boolean} [options.insensitive=true] - Whether the search should be case insensitive
2122+ * @param {string[]?} [options.filteredByTags=null] - Tags to filter characters by
2123+ * @param {boolean} [options.preferCurrentChar=true] - Whether to prefer the current character(s)
2124+ * @param {boolean} [options.quiet=false] - Whether to suppress warnings
2125+ * @returns {any?} - The found character or null if not found
2126+ */
2127+export function findChar({ name = null, allowAvatar = true, insensitive = true, filteredByTags = null, preferCurrentChar = true, quiet = false } = {}) {
2128+ const matches = (char) => (allowAvatar && char.avatar === name) || (insensitive ? equalsIgnoreCaseAndAccents(char.name, name) : char.name === name);
2129+
2130+ // Filter characters by tags if provided
2131+ let filteredCharacters = characters;
2132+ if (filteredByTags) {
2133+ filteredCharacters = characters.filter(char => {
2134+ const charTags = getTagsList(char.avatar, false);
2135+ return filteredByTags.every(tagName => charTags.some(x => x.name == tagName));
2136+ });
2137+ }
2138+
2139+ // Get the current character(s)
2140+ /** @type {any[]} */
2141+ const currentChars = selected_group ? groups.find(group => group.id === selected_group)?.members.map(member => filteredCharacters.find(char => char.avatar === member))
2142+ : [filteredCharacters.find(char => characters[this_chid]?.avatar === char.avatar)];
2143+
2144+ // If we have a current char and prefer it, return that if it matches
2145+ if (preferCurrentChar) {
2146+ const preferredCharSearch = currentChars.filter(matches);
2147+ if (preferredCharSearch.length > 1) {
2148+ if (!quiet) toastr.warning(`Multiple characters found for name "${name}" and given conditions.`);
2149+ else console.warn(`Multiple characters found for name "${name}". Returning the first match.`);
2150+ }
2151+ if (preferredCharSearch.length) {
2152+ return preferredCharSearch[0];
2153+ }
2154+ }
2155+
2156+ // If allowAvatar is true, search by avatar first
2157+ if (allowAvatar && name) {
2158+ const characterByAvatar = filteredCharacters.find(char => char.avatar === name);
2159+ if (characterByAvatar) {
2160+ return characterByAvatar;
2161+ }
2162+ }
2163+
2164+ // Search for matching characters by name
2165+ const matchingCharacters = name ? filteredCharacters.filter(matches) : filteredCharacters;
2166+ if (matchingCharacters.length > 1) {
2167+ if (!quiet) toastr.warning(`Multiple characters found for name "${name}" and given conditions.`);
2168+ else console.warn(`Multiple characters found for name "${name}". Returning the first match.`);
2169+ }
2170+
2171+ return matchingCharacters[0] || null;
2172+}
2173+
2174+/**
2175+ * Gets the index of a character based on the character object
2176+ * @param {object} char - The character object to find the index for
2177+ * @throws {Error} If the character is not found
2178+ * @returns {number} The index of the character in the characters array
2179+ */
2180+export function getCharIndex(char) {
2181+ if (!char) throw new Error('Character is undefined');
2182+ const index = characters.findIndex(c => c.avatar === char.avatar);
2183+ if (index === -1) throw new Error(`Character not found: ${char.avatar}`);
2184+ return index;
2185+}