Require single quotes

This commit is contained in:
valadaptive
2023-12-02 13:04:51 -05:00
parent a06f1e8ad6
commit a37f874e38
76 changed files with 4135 additions and 4134 deletions

View File

@ -3,15 +3,15 @@ TODO:
*/
//const DEBUG_TONY_SAMA_FORK_MODE = true
import { getRequestHeaders, callPopup } from "../../../script.js";
import { deleteExtension, extensionNames, installExtension, renderExtensionTemplate } from "../../extensions.js";
import { getStringHash, isValidUrl } from "../../utils.js";
import { getRequestHeaders, callPopup } from '../../../script.js';
import { deleteExtension, extensionNames, installExtension, renderExtensionTemplate } from '../../extensions.js';
import { getStringHash, isValidUrl } from '../../utils.js';
export { MODULE_NAME };
const MODULE_NAME = 'assets';
const DEBUG_PREFIX = "<Assets module> ";
const DEBUG_PREFIX = '<Assets module> ';
let previewAudio = null;
let ASSETS_JSON_URL = "https://raw.githubusercontent.com/SillyTavern/SillyTavern-Content/main/index.json"
let ASSETS_JSON_URL = 'https://raw.githubusercontent.com/SillyTavern/SillyTavern-Content/main/index.json'
// DBG
@ -26,29 +26,29 @@ let currentAssets = {};
function downloadAssetsList(url) {
updateCurrentAssets().then(function () {
fetch(url, { cache: "no-cache" })
fetch(url, { cache: 'no-cache' })
.then(response => response.json())
.then(json => {
availableAssets = {};
$("#assets_menu").empty();
$('#assets_menu').empty();
console.debug(DEBUG_PREFIX, "Received assets dictionary", json);
console.debug(DEBUG_PREFIX, 'Received assets dictionary', json);
for (const i of json) {
//console.log(DEBUG_PREFIX,i)
if (availableAssets[i["type"]] === undefined)
availableAssets[i["type"]] = [];
if (availableAssets[i['type']] === undefined)
availableAssets[i['type']] = [];
availableAssets[i["type"]].push(i);
availableAssets[i['type']].push(i);
}
console.debug(DEBUG_PREFIX, "Updated available assets to", availableAssets);
console.debug(DEBUG_PREFIX, 'Updated available assets to', availableAssets);
// First extensions, then everything else
const assetTypes = Object.keys(availableAssets).sort((a, b) => (a === 'extension') ? -1 : (b === 'extension') ? 1 : 0);
for (const assetType of assetTypes) {
let assetTypeMenu = $('<div />', { id: "assets_audio_ambient_div", class: "assets-list-div" });
let assetTypeMenu = $('<div />', { id: 'assets_audio_ambient_div', class: 'assets-list-div' });
assetTypeMenu.append(`<h3>${assetType}</h3>`)
if (assetType == 'extension') {
@ -61,74 +61,74 @@ function downloadAssetsList(url) {
for (const i in availableAssets[assetType]) {
const asset = availableAssets[assetType][i];
const elemId = `assets_install_${assetType}_${i}`;
let element = $('<button />', { id: elemId, type: "button", class: "asset-download-button menu_button" })
const label = $("<i class=\"fa-fw fa-solid fa-download fa-xl\"></i>");
let element = $('<button />', { id: elemId, type: 'button', class: 'asset-download-button menu_button' })
const label = $('<i class="fa-fw fa-solid fa-download fa-xl"></i>');
element.append(label);
//if (DEBUG_TONY_SAMA_FORK_MODE)
// asset["url"] = asset["url"].replace("https://github.com/SillyTavern/","https://github.com/Tony-sama/"); // DBG
console.debug(DEBUG_PREFIX, "Checking asset", asset["id"], asset["url"]);
console.debug(DEBUG_PREFIX, 'Checking asset', asset['id'], asset['url']);
const assetInstall = async function () {
element.off("click");
label.removeClass("fa-download");
element.off('click');
label.removeClass('fa-download');
this.classList.add('asset-download-button-loading');
await installAsset(asset["url"], assetType, asset["id"]);
label.addClass("fa-check");
await installAsset(asset['url'], assetType, asset['id']);
label.addClass('fa-check');
this.classList.remove('asset-download-button-loading');
element.on("click", assetDelete);
element.on("mouseenter", function () {
label.removeClass("fa-check");
label.addClass("fa-trash");
label.addClass("redOverlayGlow");
}).on("mouseleave", function () {
label.addClass("fa-check");
label.removeClass("fa-trash");
label.removeClass("redOverlayGlow");
element.on('click', assetDelete);
element.on('mouseenter', function () {
label.removeClass('fa-check');
label.addClass('fa-trash');
label.addClass('redOverlayGlow');
}).on('mouseleave', function () {
label.addClass('fa-check');
label.removeClass('fa-trash');
label.removeClass('redOverlayGlow');
});
};
const assetDelete = async function () {
element.off("click");
await deleteAsset(assetType, asset["id"]);
label.removeClass("fa-check");
label.removeClass("redOverlayGlow");
label.removeClass("fa-trash");
label.addClass("fa-download");
element.off("mouseenter").off("mouseleave");
element.on("click", assetInstall);
element.off('click');
await deleteAsset(assetType, asset['id']);
label.removeClass('fa-check');
label.removeClass('redOverlayGlow');
label.removeClass('fa-trash');
label.addClass('fa-download');
element.off('mouseenter').off('mouseleave');
element.on('click', assetInstall);
}
if (isAssetInstalled(assetType, asset["id"])) {
console.debug(DEBUG_PREFIX, "installed, checked");
label.toggleClass("fa-download");
label.toggleClass("fa-check");
element.on("click", assetDelete);
element.on("mouseenter", function () {
label.removeClass("fa-check");
label.addClass("fa-trash");
label.addClass("redOverlayGlow");
}).on("mouseleave", function () {
label.addClass("fa-check");
label.removeClass("fa-trash");
label.removeClass("redOverlayGlow");
if (isAssetInstalled(assetType, asset['id'])) {
console.debug(DEBUG_PREFIX, 'installed, checked');
label.toggleClass('fa-download');
label.toggleClass('fa-check');
element.on('click', assetDelete);
element.on('mouseenter', function () {
label.removeClass('fa-check');
label.addClass('fa-trash');
label.addClass('redOverlayGlow');
}).on('mouseleave', function () {
label.addClass('fa-check');
label.removeClass('fa-trash');
label.removeClass('redOverlayGlow');
});
}
else {
console.debug(DEBUG_PREFIX, "not installed, unchecked")
element.prop("checked", false);
element.on("click", assetInstall);
console.debug(DEBUG_PREFIX, 'not installed, unchecked')
element.prop('checked', false);
element.on('click', assetInstall);
}
console.debug(DEBUG_PREFIX, "Created element for ", asset["id"])
console.debug(DEBUG_PREFIX, 'Created element for ', asset['id'])
const displayName = DOMPurify.sanitize(asset["name"] || asset["id"]);
const description = DOMPurify.sanitize(asset["description"] || "");
const url = isValidUrl(asset["url"]) ? asset["url"] : "";
const displayName = DOMPurify.sanitize(asset['name'] || asset['id']);
const description = DOMPurify.sanitize(asset['description'] || '');
const url = isValidUrl(asset['url']) ? asset['url'] : '';
const previewIcon = assetType == 'extension' ? 'fa-arrow-up-right-from-square' : 'fa-headphones-simple';
$(`<i></i>`)
$('<i></i>')
.append(element)
.append(`<div class="flex-container flexFlowColumn">
<span class="flex-container alignitemscenter">
@ -141,17 +141,17 @@ function downloadAssetsList(url) {
</div>`)
.appendTo(assetTypeMenu);
}
assetTypeMenu.appendTo("#assets_menu");
assetTypeMenu.appendTo('#assets_menu');
assetTypeMenu.on('click', 'a.asset_preview', previewAsset);
}
$("#assets_menu").show();
$('#assets_menu').show();
})
.catch((error) => {
console.error(error);
toastr.error("Problem with assets URL", DEBUG_PREFIX + "Cannot get assets list");
$('#assets-connect-button').addClass("fa-plug-circle-exclamation");
$('#assets-connect-button').addClass("redOverlayGlow");
toastr.error('Problem with assets URL', DEBUG_PREFIX + 'Cannot get assets list');
$('#assets-connect-button').addClass('fa-plug-circle-exclamation');
$('#assets-connect-button').addClass('redOverlayGlow');
});
});
}
@ -182,7 +182,7 @@ function isAssetInstalled(assetType, filename) {
let assetList = currentAssets[assetType];
if (assetType == 'extension') {
const thirdPartyMarker = "third-party/";
const thirdPartyMarker = 'third-party/';
assetList = extensionNames.filter(x => x.startsWith(thirdPartyMarker)).map(x => x.replace(thirdPartyMarker, ''));
}
@ -196,13 +196,13 @@ function isAssetInstalled(assetType, filename) {
}
async function installAsset(url, assetType, filename) {
console.debug(DEBUG_PREFIX, "Downloading ", url);
console.debug(DEBUG_PREFIX, 'Downloading ', url);
const category = assetType;
try {
if (category === 'extension') {
console.debug(DEBUG_PREFIX, "Installing extension ", url)
console.debug(DEBUG_PREFIX, 'Installing extension ', url)
await installExtension(url);
console.debug(DEBUG_PREFIX, "Extension installed.")
console.debug(DEBUG_PREFIX, 'Extension installed.')
return;
}
@ -214,7 +214,7 @@ async function installAsset(url, assetType, filename) {
cache: 'no-cache',
});
if (result.ok) {
console.debug(DEBUG_PREFIX, "Download success.")
console.debug(DEBUG_PREFIX, 'Download success.')
}
}
catch (err) {
@ -224,13 +224,13 @@ async function installAsset(url, assetType, filename) {
}
async function deleteAsset(assetType, filename) {
console.debug(DEBUG_PREFIX, "Deleting ", assetType, filename);
console.debug(DEBUG_PREFIX, 'Deleting ', assetType, filename);
const category = assetType;
try {
if (category === 'extension') {
console.debug(DEBUG_PREFIX, "Deleting extension ", filename)
console.debug(DEBUG_PREFIX, 'Deleting extension ', filename)
await deleteExtension(filename);
console.debug(DEBUG_PREFIX, "Extension deleted.")
console.debug(DEBUG_PREFIX, 'Extension deleted.')
}
const body = { category, filename };
@ -241,7 +241,7 @@ async function deleteAsset(assetType, filename) {
cache: 'no-cache',
});
if (result.ok) {
console.debug(DEBUG_PREFIX, "Deletion success.")
console.debug(DEBUG_PREFIX, 'Deletion success.')
}
}
catch (err) {
@ -255,9 +255,9 @@ async function deleteAsset(assetType, filename) {
//#############################//
async function updateCurrentAssets() {
console.debug(DEBUG_PREFIX, "Checking installed assets...")
console.debug(DEBUG_PREFIX, 'Checking installed assets...')
try {
const result = await fetch(`/api/assets/get`, {
const result = await fetch('/api/assets/get', {
method: 'POST',
headers: getRequestHeaders(),
});
@ -266,7 +266,7 @@ async function updateCurrentAssets() {
catch (err) {
console.log(err);
}
console.debug(DEBUG_PREFIX, "Current assets found:", currentAssets)
console.debug(DEBUG_PREFIX, 'Current assets found:', currentAssets)
}
@ -283,7 +283,7 @@ jQuery(async () => {
assetsJsonUrl.val(ASSETS_JSON_URL);
const connectButton = windowHtml.find('#assets-connect-button');
connectButton.on("click", async function () {
connectButton.on('click', async function () {
const url = String(assetsJsonUrl.val());
const rememberKey = `Assets_SkipConfirm_${getStringHash(url)}`;
const skipConfirm = localStorage.getItem(rememberKey) === 'true';
@ -298,21 +298,21 @@ jQuery(async () => {
localStorage.setItem(rememberKey, String(rememberValue));
}
console.debug(DEBUG_PREFIX, "Confimation, loading assets...");
console.debug(DEBUG_PREFIX, 'Confimation, loading assets...');
downloadAssetsList(url);
connectButton.removeClass("fa-plug-circle-exclamation");
connectButton.removeClass("redOverlayGlow");
connectButton.addClass("fa-plug-circle-check");
connectButton.removeClass('fa-plug-circle-exclamation');
connectButton.removeClass('redOverlayGlow');
connectButton.addClass('fa-plug-circle-check');
} catch (error) {
console.error('Error:', error);
toastr.error(`Cannot get assets list from ${url}`);
connectButton.removeClass("fa-plug-circle-check");
connectButton.addClass("fa-plug-circle-exclamation");
connectButton.removeClass("redOverlayGlow");
connectButton.removeClass('fa-plug-circle-check');
connectButton.addClass('fa-plug-circle-exclamation');
connectButton.removeClass('redOverlayGlow');
}
}
else {
console.debug(DEBUG_PREFIX, "Connection refused by user");
console.debug(DEBUG_PREFIX, 'Connection refused by user');
}
});

View File

@ -1,9 +1,9 @@
import { getBase64Async, saveBase64AsFile } from "../../utils.js";
import { getContext, getApiUrl, doExtrasFetch, extension_settings, modules } from "../../extensions.js";
import { callPopup, getRequestHeaders, saveSettingsDebounced, substituteParams } from "../../../script.js";
import { getMessageTimeStamp } from "../../RossAscends-mods.js";
import { SECRET_KEYS, secret_state } from "../../secrets.js";
import { getMultimodalCaption } from "../shared.js";
import { getBase64Async, saveBase64AsFile } from '../../utils.js';
import { getContext, getApiUrl, doExtrasFetch, extension_settings, modules } from '../../extensions.js';
import { callPopup, getRequestHeaders, saveSettingsDebounced, substituteParams } from '../../../script.js';
import { getMessageTimeStamp } from '../../RossAscends-mods.js';
import { SECRET_KEYS, secret_state } from '../../secrets.js';
import { getMultimodalCaption } from '../shared.js';
export { MODULE_NAME };
const MODULE_NAME = 'caption';
@ -285,7 +285,7 @@ jQuery(function () {
});
}
function addPictureSendForm() {
const inputHtml = `<input id="img_file" type="file" hidden accept="image/*">`;
const inputHtml = '<input id="img_file" type="file" hidden accept="image/*">';
const imgForm = document.createElement('form');
imgForm.id = 'img_form';
$(imgForm).append(inputHtml);

View File

@ -1,10 +1,10 @@
import { callPopup, eventSource, event_types, getRequestHeaders, saveSettingsDebounced } from "../../../script.js";
import { dragElement, isMobile } from "../../RossAscends-mods.js";
import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch, renderExtensionTemplate } from "../../extensions.js";
import { loadMovingUIState, power_user } from "../../power-user.js";
import { registerSlashCommand } from "../../slash-commands.js";
import { onlyUnique, debounce, getCharaFilename, trimToEndSentence, trimToStartSentence } from "../../utils.js";
import { hideMutedSprites } from "../../group-chats.js";
import { callPopup, eventSource, event_types, getRequestHeaders, saveSettingsDebounced } from '../../../script.js';
import { dragElement, isMobile } from '../../RossAscends-mods.js';
import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch, renderExtensionTemplate } from '../../extensions.js';
import { loadMovingUIState, power_user } from '../../power-user.js';
import { registerSlashCommand } from '../../slash-commands.js';
import { onlyUnique, debounce, getCharaFilename, trimToEndSentence, trimToStartSentence } from '../../utils.js';
import { hideMutedSprites } from '../../group-chats.js';
export { MODULE_NAME };
const MODULE_NAME = 'expressions';
@ -12,35 +12,35 @@ const UPDATE_INTERVAL = 2000;
const STREAMING_UPDATE_INTERVAL = 6000;
const FALLBACK_EXPRESSION = 'joy';
const DEFAULT_EXPRESSIONS = [
"talkinghead",
"admiration",
"amusement",
"anger",
"annoyance",
"approval",
"caring",
"confusion",
"curiosity",
"desire",
"disappointment",
"disapproval",
"disgust",
"embarrassment",
"excitement",
"fear",
"gratitude",
"grief",
"joy",
"love",
"nervousness",
"optimism",
"pride",
"realization",
"relief",
"remorse",
"sadness",
"surprise",
"neutral"
'talkinghead',
'admiration',
'amusement',
'anger',
'annoyance',
'approval',
'caring',
'confusion',
'curiosity',
'desire',
'disappointment',
'disapproval',
'disgust',
'embarrassment',
'excitement',
'fear',
'gratitude',
'grief',
'joy',
'love',
'nervousness',
'optimism',
'pride',
'realization',
'relief',
'remorse',
'sadness',
'surprise',
'neutral'
];
let expressionsList = null;
@ -445,7 +445,7 @@ function handleImageChange() {
const imgElement = document.querySelector('img#expression-image.expression');
if (!imgElement || !(imgElement instanceof HTMLImageElement)) {
console.log("Cannot find addExpressionImage()");
console.log('Cannot find addExpressionImage()');
return;
}
@ -471,7 +471,7 @@ function handleImageChange() {
}
}
} else {
imgElement.src = ""; //remove incase char doesnt have expressions
imgElement.src = ''; //remove incase char doesnt have expressions
setExpression(getContext().name2, FALLBACK_EXPRESSION, true);
}
}
@ -509,7 +509,7 @@ async function moduleWorker() {
if (vnStateChanged) {
lastMessage = null;
$('#visual-novel-wrapper').empty();
$("#expression-holder").css({ top: '', left: '', right: '', bottom: '', height: '', width: '', margin: '' });
$('#expression-holder').css({ top: '', left: '', right: '', bottom: '', height: '', width: '', margin: '' });
}
const currentLastMessage = getLastCharacterMessage();
@ -687,7 +687,7 @@ function getFolderNameByMessage(message) {
return '';
}
const folderName = avatarPath.replace(/\.[^/.]+$/, "");
const folderName = avatarPath.replace(/\.[^/.]+$/, '');
return folderName;
}
@ -716,7 +716,7 @@ async function setSpriteSetCommand(_, folder) {
folder = `${currentLastMessage.name}/${folder}`;
}
$("#expression_override").val(folder.trim());
$('#expression_override').val(folder.trim());
onClickExpressionOverrideButton();
removeExpression();
moduleWorker();
@ -1037,7 +1037,7 @@ async function setExpression(character, expression, force) {
//add new sprite path to clone src
expressionClone.attr('src', sprite.path);
//add invisible clone to html
expressionClone.appendTo($("#expression-holder"))
expressionClone.appendTo($('#expression-holder'))
const duration = 200;
@ -1105,7 +1105,7 @@ async function setExpression(character, expression, force) {
img.attr('src', defImgUrl);
img.addClass('default');
}
document.getElementById("expression-holder").style.display = '';
document.getElementById('expression-holder').style.display = '';
} else {
@ -1203,7 +1203,7 @@ async function onClickExpressionRemoveCustom() {
async function handleFileUpload(url, formData) {
try {
const data = await jQuery.ajax({
type: "POST",
type: 'POST',
url: url,
data: formData,
beforeSend: function () { },
@ -1266,7 +1266,7 @@ async function onClickExpressionOverrideButton() {
return;
}
const overridePath = String($("#expression_override").val());
const overridePath = String($('#expression_override').val());
const existingOverrideIndex = extension_settings.expressionOverrides.findIndex((e) =>
e.name == avatarFileName
);
@ -1317,7 +1317,7 @@ async function onClickExpressionOverrideRemoveAllButton() {
extension_settings.expressionOverrides = [];
saveSettingsDebounced();
console.debug("All expression image overrides have been cleared.");
console.debug('All expression image overrides have been cleared.');
// Refresh sprites list to use the default name if applicable
try {
@ -1365,7 +1365,7 @@ async function onClickExpressionDelete(event) {
// Prevents the expression from being set
event.stopPropagation();
const confirmation = await callPopup("<h3>Are you sure?</h3>Once deleted, it's gone forever!", 'confirm');
const confirmation = await callPopup('<h3>Are you sure?</h3>Once deleted, it\'s gone forever!', 'confirm');
if (!confirmation) {
return;
@ -1401,13 +1401,13 @@ function setExpressionOverrideHtml(forceClear = false) {
);
if (expressionOverride && expressionOverride.path) {
$("#expression_override").val(expressionOverride.path);
$('#expression_override').val(expressionOverride.path);
} else if (expressionOverride) {
delete extension_settings.expressionOverrides[expressionOverride.name];
}
if (forceClear && !expressionOverride) {
$("#expression_override").val("");
$('#expression_override').val('');
}
}
@ -1450,8 +1450,8 @@ function setExpressionOverrideHtml(forceClear = false) {
$(document).on('click', '.expression_list_item', onClickExpressionImage);
$(document).on('click', '.expression_list_upload', onClickExpressionUpload);
$(document).on('click', '.expression_list_delete', onClickExpressionDelete);
$(window).on("resize", updateVisualNovelModeDebounced);
$("#open_chat_expressions").hide();
$(window).on('resize', updateVisualNovelModeDebounced);
$('#open_chat_expressions').hide();
$('#image_type_toggle').on('click', function () {
if (this instanceof HTMLInputElement) {
@ -1472,7 +1472,7 @@ function setExpressionOverrideHtml(forceClear = false) {
const updateFunction = wrapper.update.bind(wrapper);
setInterval(updateFunction, UPDATE_INTERVAL);
moduleWorker();
dragElement($("#expression-holder"))
dragElement($('#expression-holder'))
eventSource.on(event_types.CHAT_CHANGED, () => {
// character changed
removeExpression();
@ -1481,7 +1481,7 @@ function setExpressionOverrideHtml(forceClear = false) {
//clear expression
let imgElement = document.getElementById('expression-image');
if (imgElement && imgElement instanceof HTMLImageElement) {
imgElement.src = "";
imgElement.src = '';
}
//set checkbox to global var

View File

@ -3,14 +3,14 @@ import {
this_chid,
characters,
getRequestHeaders,
} from "../../../script.js";
import { selected_group } from "../../group-chats.js";
import { loadFileToDocument, delay } from "../../utils.js";
} from '../../../script.js';
import { selected_group } from '../../group-chats.js';
import { loadFileToDocument, delay } from '../../utils.js';
import { loadMovingUIState } from '../../power-user.js';
import { dragElement } from '../../RossAscends-mods.js';
import { registerSlashCommand } from "../../slash-commands.js";
import { registerSlashCommand } from '../../slash-commands.js';
const extensionName = "gallery";
const extensionName = 'gallery';
const extensionFolderPath = `scripts/extensions/${extensionName}/`;
let firstTime = true;
@ -38,7 +38,7 @@ async function getGalleryItems(url) {
const items = data.map((file) => ({
src: `user/images/${url}/${file}`,
srct: `user/images/${url}/${file}`,
title: "", // Optional title for each item
title: '', // Optional title for each item
}));
return items;
@ -54,8 +54,8 @@ async function getGalleryItems(url) {
* @returns {Promise<void>} - Promise representing the completion of the gallery initialization.
*/
async function initGallery(items, url) {
$("#dragGallery").nanogallery2({
"items": items,
$('#dragGallery').nanogallery2({
'items': items,
thumbnailWidth: 'auto',
thumbnailHeight: thumbnailHeight,
paginationVisiblePages: paginationVisiblePages,
@ -72,13 +72,13 @@ async function initGallery(items, url) {
thumbnailIcon: { padding: '5px', color: '#fff', shadow: '' },
pagination: { background: '#181818', backgroundSelected: '#666', color: '#fff', borderRadius: '2px', shapeBorder: '3px solid var(--SmartThemeQuoteColor)', shapeColor: '#444', shapeSelectedColor: '#aaa' }
},
galleryDisplayMode: "pagination",
galleryDisplayMode: 'pagination',
fnThumbnailOpen: viewWithDragbox,
});
eventSource.on('resizeUI', function (elmntName) {
jQuery("#dragGallery").nanogallery2('resize');
jQuery('#dragGallery').nanogallery2('resize');
});
const dropZone = $('#dragGallery');
@ -113,9 +113,9 @@ async function initGallery(items, url) {
//let images populate first
await delay(100)
//unset the height (which must be getting set by the gallery library at some point)
$("#dragGallery").css('height', 'unset');
$('#dragGallery').css('height', 'unset');
//force a resize to make images display correctly
jQuery("#dragGallery").nanogallery2('resize');
jQuery('#dragGallery').nanogallery2('resize');
}
/**
@ -135,27 +135,27 @@ async function showCharGallery() {
if (firstTime) {
await loadFileToDocument(
`${extensionFolderPath}nanogallery2.woff.min.css`,
"css"
'css'
);
await loadFileToDocument(
`${extensionFolderPath}jquery.nanogallery2.min.js`,
"js"
'js'
);
firstTime = false;
toastr.info("Images can also be found in the folder `user/images`", "Drag and drop images onto the gallery to upload them", { timeOut: 6000 });
toastr.info('Images can also be found in the folder `user/images`', 'Drag and drop images onto the gallery to upload them', { timeOut: 6000 });
}
try {
let url = selected_group || this_chid;
if (!selected_group && this_chid) {
const char = characters[this_chid];
url = char.avatar.replace(".png", "");
url = char.avatar.replace('.png', '');
}
const items = await getGalleryItems(url);
// if there already is a gallery, destroy it and place this one in its place
if ($(`#dragGallery`).length) {
$(`#dragGallery`).nanogallery2("destroy");
if ($('#dragGallery').length) {
$('#dragGallery').nanogallery2('destroy');
initGallery(items, url);
} else {
makeMovable();
@ -216,13 +216,13 @@ async function uploadFile(file, url) {
toastr.success('File uploaded successfully. Saved at: ' + result.path);
// Refresh the gallery
$("#dragGallery").nanogallery2("destroy"); // Destroy old gallery
$('#dragGallery').nanogallery2('destroy'); // Destroy old gallery
const newItems = await getGalleryItems(url); // Fetch the latest items
initGallery(newItems, url); // Reinitialize the gallery with new items and pass 'url'
} catch (error) {
console.error("There was an issue uploading the file:", error);
console.error('There was an issue uploading the file:', error);
// Replacing alert with toastr error notification
toastr.error('Failed to upload the file.');
@ -233,17 +233,17 @@ async function uploadFile(file, url) {
$(document).ready(function () {
// Register an event listener
eventSource.on("charManagementDropdown", (selectedOptionId) => {
if (selectedOptionId === "show_char_gallery") {
eventSource.on('charManagementDropdown', (selectedOptionId) => {
if (selectedOptionId === 'show_char_gallery') {
showCharGallery();
}
});
// Add an option to the dropdown
$("#char-management-dropdown").append(
$("<option>", {
id: "show_char_gallery",
text: "Show Gallery",
$('#char-management-dropdown').append(
$('<option>', {
id: 'show_char_gallery',
text: 'Show Gallery',
})
);
});
@ -254,7 +254,7 @@ $(document).ready(function () {
* The cloned element has its attributes set, a new child div appended, and is made visible on the body.
* Additionally, it sets up the element to prevent dragging on its images.
*/
function makeMovable(id = "gallery") {
function makeMovable(id = 'gallery') {
console.debug('making new container from template')
const template = $('#generic_draggable_template').html();
@ -265,7 +265,7 @@ function makeMovable(id = "gallery") {
newElement.find('.drag-grabber').attr('id', `${id}header`);
newElement.find('.dragTitle').text('Image Gallery')
//add a div for the gallery
newElement.append(`<div id="dragGallery"></div>`);
newElement.append('<div id="dragGallery"></div>');
// add no-scrollbar class to this element
newElement.addClass('no-scrollbar');
@ -274,7 +274,7 @@ function makeMovable(id = "gallery") {
closeButton.attr('id', `${id}close`);
closeButton.attr('data-related-id', `${id}`);
$(`#dragGallery`).css('display', 'block');
$('#dragGallery').css('display', 'block');
$('body').append(newElement);
@ -370,7 +370,7 @@ function makeDragImg(id, url) {
return false;
});
} else {
console.error("Failed to append the template content or retrieve the appended content.");
console.error('Failed to append the template content or retrieve the appended content.');
}
$('body').on('click', '.dragClose', function () {
@ -415,7 +415,7 @@ function viewWithDragbox(items) {
// Registers a simple command for opening the char gallery.
registerSlashCommand("show-gallery", showGalleryCommand, ["sg"], " shows the gallery", true, true);
registerSlashCommand('show-gallery', showGalleryCommand, ['sg'], ' shows the gallery', true, true);
function showGalleryCommand(args) {
showCharGallery();

View File

@ -1,10 +1,10 @@
import { getStringHash, debounce, waitUntilCondition, extractAllWords } from "../../utils.js";
import { getContext, getApiUrl, extension_settings, doExtrasFetch, modules } from "../../extensions.js";
import { eventSource, event_types, extension_prompt_types, generateQuietPrompt, is_send_press, saveSettingsDebounced, substituteParams } from "../../../script.js";
import { is_group_generating, selected_group } from "../../group-chats.js";
import { registerSlashCommand } from "../../slash-commands.js";
import { getStringHash, debounce, waitUntilCondition, extractAllWords } from '../../utils.js';
import { getContext, getApiUrl, extension_settings, doExtrasFetch, modules } from '../../extensions.js';
import { eventSource, event_types, extension_prompt_types, generateQuietPrompt, is_send_press, saveSettingsDebounced, substituteParams } from '../../../script.js';
import { is_group_generating, selected_group } from '../../group-chats.js';
import { registerSlashCommand } from '../../slash-commands.js';
import { loadMovingUIState } from '../../power-user.js';
import { dragElement } from "../../RossAscends-mods.js";
import { dragElement } from '../../RossAscends-mods.js';
export { MODULE_NAME };
const MODULE_NAME = '1_memory';
@ -564,7 +564,7 @@ function setMemoryContext(value, saveToMessage) {
function doPopout(e) {
const target = e.target;
//repurposes the zoomed avatar template to server as a floating div
if ($("#summaryExtensionPopout").length === 0) {
if ($('#summaryExtensionPopout').length === 0) {
console.debug('did not see popout yet, creating')
const originalHTMLClone = $(target).parent().parent().parent().find('.inline-drawer-content').html()
const originalElement = $(target).parent().parent().parent().find('.inline-drawer-content')
@ -580,32 +580,32 @@ function doPopout(e) {
.empty()
const prevSummaryBoxContents = $('#memory_contents').val(); //copy summary box before emptying
originalElement.empty();
originalElement.html(`<div class="flex-container alignitemscenter justifyCenter wide100p"><small>Currently popped out</small></div>`)
originalElement.html('<div class="flex-container alignitemscenter justifyCenter wide100p"><small>Currently popped out</small></div>')
newElement.append(controlBarHtml).append(originalHTMLClone)
$('body').append(newElement);
$("#summaryExtensionDrawerContents").addClass('scrollableInnerFull')
$('#summaryExtensionDrawerContents').addClass('scrollableInnerFull')
setMemoryContext(prevSummaryBoxContents, false); //paste prev summary box contents into popout box
setupListeners();
loadSettings();
loadMovingUIState();
$("#summaryExtensionPopout").fadeIn(250);
$('#summaryExtensionPopout').fadeIn(250);
dragElement(newElement);
//setup listener for close button to restore extensions menu
$('#summaryExtensionPopoutClose').off('click').on('click', function () {
$("#summaryExtensionDrawerContents").removeClass('scrollableInnerFull')
const summaryPopoutHTML = $("#summaryExtensionDrawerContents")
$("#summaryExtensionPopout").fadeOut(250, () => {
$('#summaryExtensionDrawerContents').removeClass('scrollableInnerFull')
const summaryPopoutHTML = $('#summaryExtensionDrawerContents')
$('#summaryExtensionPopout').fadeOut(250, () => {
originalElement.empty();
originalElement.html(summaryPopoutHTML);
$("#summaryExtensionPopout").remove()
$('#summaryExtensionPopout').remove()
})
loadSettings();
})
} else {
console.debug('saw existing popout, removing')
$("#summaryExtensionPopout").fadeOut(250, () => { $("#summaryExtensionPopoutClose").trigger('click') });
$('#summaryExtensionPopout').fadeOut(250, () => { $('#summaryExtensionPopoutClose').trigger('click') });
}
}
@ -629,9 +629,9 @@ function setupListeners() {
$('#memory_depth').off('click').on('input', onMemoryDepthInput);
$('input[name="memory_position"]').off('click').on('change', onMemoryPositionChange);
$('#memory_prompt_words_force').off('click').on('input', onMemoryPromptWordsForceInput);
$("#summarySettingsBlockToggle").off('click').on('click', function () {
$('#summarySettingsBlockToggle').off('click').on('click', function () {
console.log('saw settings button click')
$("#summarySettingsBlock").slideToggle(200, "swing"); //toggleClass("hidden");
$('#summarySettingsBlock').slideToggle(200, 'swing'); //toggleClass("hidden");
});
}
@ -730,7 +730,7 @@ jQuery(function () {
`;
$('#extensions_settings2').append(settingsHtml);
setupListeners();
$("#summaryExtensionPopoutButton").off('click').on('click', function (e) {
$('#summaryExtensionPopoutButton').off('click').on('click', function (e) {
doPopout(e);
e.stopPropagation();
});

View File

@ -1,12 +1,12 @@
import { saveSettingsDebounced, callPopup, getRequestHeaders, substituteParams, eventSource, event_types } from "../../../script.js";
import { getContext, extension_settings } from "../../extensions.js";
import { initScrollHeight, resetScrollHeight, getSortableDelay, escapeHtml } from "../../utils.js";
import { executeSlashCommands, registerSlashCommand } from "../../slash-commands.js";
import { ContextMenu } from "./src/ContextMenu.js";
import { MenuItem } from "./src/MenuItem.js";
import { MenuHeader } from "./src/MenuHeader.js";
import { loadMovingUIState } from "../../power-user.js";
import { dragElement } from "../../RossAscends-mods.js";
import { saveSettingsDebounced, callPopup, getRequestHeaders, substituteParams, eventSource, event_types } from '../../../script.js';
import { getContext, extension_settings } from '../../extensions.js';
import { initScrollHeight, resetScrollHeight, getSortableDelay, escapeHtml } from '../../utils.js';
import { executeSlashCommands, registerSlashCommand } from '../../slash-commands.js';
import { ContextMenu } from './src/ContextMenu.js';
import { MenuItem } from './src/MenuItem.js';
import { MenuHeader } from './src/MenuHeader.js';
import { loadMovingUIState } from '../../power-user.js';
import { dragElement } from '../../RossAscends-mods.js';
export { MODULE_NAME };
@ -26,8 +26,8 @@ const defaultSettings = {
//method from worldinfo
async function updateQuickReplyPresetList() {
const result = await fetch("/getsettings", {
method: "POST",
const result = await fetch('/getsettings', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({}),
});
@ -36,7 +36,7 @@ async function updateQuickReplyPresetList() {
var data = await result.json();
presets = data.quickReplyPresets?.length ? data.quickReplyPresets : [];
console.debug('Quick Reply presets', presets);
$("#quickReplyPresets").find('option[value!=""]').remove();
$('#quickReplyPresets').find('option[value!=""]').remove();
if (presets !== undefined) {
@ -45,7 +45,7 @@ async function updateQuickReplyPresetList() {
option.value = item.name;
option.innerText = item.name;
option.selected = selected_preset.includes(item.name);
$("#quickReplyPresets").append(option);
$('#quickReplyPresets').append(option);
});
}
}
@ -115,7 +115,7 @@ async function onQuickReplyContextMenuChange(id) {
async function onQuickReplyCtxButtonClick(id) {
const editorHtml = $(await $.get('scripts/extensions/quick-reply/contextMenuEditor.html'));
const popupResult = callPopup(editorHtml, "confirm", undefined, { okButton: "Save", wide: false, large: false, rows: 1 });
const popupResult = callPopup(editorHtml, 'confirm', undefined, { okButton: 'Save', wide: false, large: false, rows: 1 });
const qr = extension_settings.quickReply.quickReplySlots[id - 1];
if (!qr.contextMenu) {
qr.contextMenu = [];
@ -207,8 +207,8 @@ async function onQuickReplyEnabledInput() {
let isEnabled = $(this).prop('checked')
extension_settings.quickReply.quickReplyEnabled = !!isEnabled;
if (isEnabled === true) {
$("#quickReplyBar").show();
} else { $("#quickReplyBar").hide(); }
$('#quickReplyBar').show();
} else { $('#quickReplyBar').hide(); }
saveSettingsDebounced();
}
@ -254,7 +254,7 @@ async function performQuickReply(prompt, index) {
console.warn(`Quick reply slot ${index} is empty! Aborting.`);
return;
}
const existingText = $("#send_textarea").val();
const existingText = $('#send_textarea').val();
let newText;
@ -277,14 +277,14 @@ async function performQuickReply(prompt, index) {
newText = substituteParams(newText);
$("#send_textarea").val(newText);
$('#send_textarea').val(newText);
// Set the focus back to the textarea
$("#send_textarea").trigger('focus');
$('#send_textarea').trigger('focus');
// Only trigger send button if quickActionEnabled is not checked or
if (!extension_settings.quickReply.quickActionEnabled) {
$("#send_but").trigger('click');
$('#send_but').trigger('click');
}
}
@ -327,10 +327,10 @@ function buildContextMenu(qr, chainMes = null, hierarchy = [], labelHierarchy =
async function doQuickReplyBarPopout() {
//shared elements
const newQuickRepliesDiv = `<div id="quickReplies"></div>`
const popoutButtonClone = $("#quickReplyPopoutButton")
const newQuickRepliesDiv = '<div id="quickReplies"></div>'
const popoutButtonClone = $('#quickReplyPopoutButton')
if ($("#quickReplyBarPopout").length === 0) {
if ($('#quickReplyBarPopout').length === 0) {
console.debug('did not see popout yet, creating')
const template = $('#zoomed_avatar_template').html();
const controlBarHtml = `<div class="panelControlBar flex-container">
@ -346,10 +346,10 @@ async function doQuickReplyBarPopout() {
.append(controlBarHtml)
.append(newQuickRepliesDiv)
//empty original bar
$("#quickReplyBar").empty()
$('#quickReplyBar').empty()
//add clone in popout
$('body').append(newElement);
$("#quickReplies").append(quickRepliesClone).css('margin-top', '1em')
$('#quickReplies').append(quickRepliesClone).css('margin-top', '1em')
$('.quickReplyButton').on('click', function () {
let index = $(this).data('index');
sendQuickReply(index);
@ -377,16 +377,16 @@ async function doQuickReplyBarPopout() {
});
loadMovingUIState();
$("#quickReplyBarPopout").fadeIn(250)
$('#quickReplyBarPopout').fadeIn(250)
dragElement(newElement)
$('#quickReplyBarPopoutClose').off('click').on('click', function () {
console.debug('saw existing popout, removing')
let quickRepliesClone = $('#quickReplies').html()
$("#quickReplyBar").append(newQuickRepliesDiv)
$("#quickReplies").prepend(quickRepliesClone)
$("#quickReplyBar").append(popoutButtonClone).fadeIn(250)
$("#quickReplyBarPopout").fadeOut(250, () => { $("#quickReplyBarPopout").remove() });
$('#quickReplyBar').append(newQuickRepliesDiv)
$('#quickReplies').prepend(quickRepliesClone)
$('#quickReplyBar').append(popoutButtonClone).fadeIn(250)
$('#quickReplyBarPopout').fadeOut(250, () => { $('#quickReplyBarPopout').remove() });
$('.quickReplyButton').on('click', function () {
let index = $(this).data('index');
sendQuickReply(index);
@ -412,7 +412,7 @@ async function doQuickReplyBarPopout() {
menu.show(evt);
}
});
$("#quickReplyPopoutButton").off('click').on('click', doQuickReplyBarPopout)
$('#quickReplyPopoutButton').off('click').on('click', doQuickReplyBarPopout)
})
}
@ -421,11 +421,11 @@ async function doQuickReplyBarPopout() {
function addQuickReplyBar() {
let quickReplyButtonHtml = '';
var targetContainer;
if ($("#quickReplyBarPopout").length !== 0) {
if ($('#quickReplyBarPopout').length !== 0) {
targetContainer = 'popout'
} else {
targetContainer = 'bar'
$("#quickReplyBar").remove();
$('#quickReplyBar').remove();
}
for (let i = 0; i < extension_settings.quickReply.numberOfSlots; i++) {
@ -452,7 +452,7 @@ function addQuickReplyBar() {
if (targetContainer === 'bar') {
$('#send_form').prepend(quickReplyBarFullHtml);
} else {
$("#quickReplies").empty().append(quickReplyButtonHtml)
$('#quickReplies').empty().append(quickReplyButtonHtml)
}
@ -460,7 +460,7 @@ function addQuickReplyBar() {
let index = $(this).data('index');
sendQuickReply(index);
});
$("#quickReplyPopoutButton").off('click').on('click', doQuickReplyBarPopout)
$('#quickReplyPopoutButton').off('click').on('click', doQuickReplyBarPopout)
$('.quickReplyButton > .ctx-expander').on('click', function (evt) {
evt.stopPropagation();
let index = $(this.closest('.quickReplyButton')).data('index');
@ -538,7 +538,7 @@ async function saveQuickReplyPreset() {
//just a copy of save function with the name hardcoded to currently selected preset
async function updateQuickReplyPreset() {
const name = $("#quickReplyPresets").val()
const name = $('#quickReplyPresets').val()
if (!name) {
return;
@ -684,7 +684,7 @@ async function doQR(_, text) {
//ex: user inputs "/qr 2" >> qr with data-index 1 (but 2nd item displayed) gets triggered
let QRnum = Number(text - 1)
if (QRnum <= 0) { QRnum = 0 }
const whichQR = $("#quickReplies").find(`[data-index='${QRnum}']`);
const whichQR = $('#quickReplies').find(`[data-index='${QRnum}']`);
whichQR.trigger('click')
}
@ -865,15 +865,15 @@ jQuery(async () => {
$('#AutoInputInject').on('input', onAutoInputInject);
$('#quickReplyEnabled').on('input', onQuickReplyEnabledInput);
$('#quickReplyNumberOfSlotsApply').on('click', onQuickReplyNumberOfSlotsInput);
$("#quickReplyPresetSaveButton").on('click', saveQuickReplyPreset);
$("#quickReplyPresetUpdateButton").on('click', updateQuickReplyPreset);
$('#quickReplyPresetSaveButton').on('click', saveQuickReplyPreset);
$('#quickReplyPresetUpdateButton').on('click', updateQuickReplyPreset);
$('#quickReplyContainer').sortable({
delay: getSortableDelay(),
stop: saveQROrder,
});
$("#quickReplyPresets").on('change', async function () {
$('#quickReplyPresets').on('change', async function () {
const quickReplyPresetSelected = $(this).find(':selected').val();
extension_settings.quickReplyPreset = quickReplyPresetSelected;
applyQuickReplyPreset(quickReplyPresetSelected);

View File

@ -1,4 +1,4 @@
import { MenuItem } from "./MenuItem.js";
import { MenuItem } from './MenuItem.js';
export class MenuHeader extends MenuItem {
constructor(/**@type {String}*/label) {

View File

@ -1,4 +1,4 @@
import { SubMenu } from "./SubMenu.js";
import { SubMenu } from './SubMenu.js';
export class MenuItem {
/**@type {String}*/ label;

View File

@ -1,5 +1,5 @@
import { substituteParams } from "../../../script.js";
import { extension_settings } from "../../extensions.js";
import { substituteParams } from '../../../script.js';
import { extension_settings } from '../../extensions.js';
export {
regex_placement,
getRegexedString,
@ -40,7 +40,7 @@ function regexFromString(input) {
// Parent function to fetch a regexed version of a raw string
function getRegexedString(rawString, placement, { characterOverride, isMarkdown, isPrompt } = {}) {
let finalString = rawString;
if (extension_settings.disabledExtensions.includes("regex") || !rawString || placement === undefined) {
if (extension_settings.disabledExtensions.includes('regex') || !rawString || placement === undefined) {
return finalString;
}
@ -121,7 +121,7 @@ function filterString(rawString, trimStrings, { characterOverride } = {}) {
let finalString = rawString;
trimStrings.forEach((trimString) => {
const subTrimString = substituteParams(trimString, undefined, characterOverride);
finalString = finalString.replaceAll(subTrimString, "");
finalString = finalString.replaceAll(subTrimString, '');
});
return finalString;
@ -135,7 +135,7 @@ function substituteRegexParams(rawString, regexMatch, { characterOverride, repla
let overlaidMatch = regexMatch;
// TODO: Maybe move the for loops into a separate function?
if (replaceStrategy === regex_replace_strategy.OVERLAY) {
const splitReplace = finalString.split("{{match}}");
const splitReplace = finalString.split('{{match}}');
// There's a prefix
if (splitReplace[0]) {
@ -177,7 +177,7 @@ function substituteRegexParams(rawString, regexMatch, { characterOverride, repla
}
// Only one match is replaced. This is by design
finalString = finalString.replace("{{match}}", overlaidMatch) || finalString.replace("{{match}}", regexMatch);
finalString = finalString.replace('{{match}}', overlaidMatch) || finalString.replace('{{match}}', regexMatch);
return finalString;
}

View File

@ -1,16 +1,16 @@
import { callPopup, getCurrentChatId, reloadCurrentChat, saveSettingsDebounced } from "../../../script.js";
import { extension_settings } from "../../extensions.js";
import { registerSlashCommand } from "../../slash-commands.js";
import { getSortableDelay, uuidv4 } from "../../utils.js";
import { resolveVariable } from "../../variables.js";
import { regex_placement, runRegexScript } from "./engine.js";
import { callPopup, getCurrentChatId, reloadCurrentChat, saveSettingsDebounced } from '../../../script.js';
import { extension_settings } from '../../extensions.js';
import { registerSlashCommand } from '../../slash-commands.js';
import { getSortableDelay, uuidv4 } from '../../utils.js';
import { resolveVariable } from '../../variables.js';
import { regex_placement, runRegexScript } from './engine.js';
async function saveRegexScript(regexScript, existingScriptIndex) {
// If not editing
// Is the script name undefined or empty?
if (!regexScript.scriptName) {
toastr.error(`Could not save regex script: The script name was undefined or empty!`);
toastr.error('Could not save regex script: The script name was undefined or empty!');
return;
}
@ -32,12 +32,12 @@ async function saveRegexScript(regexScript, existingScriptIndex) {
// Is a find regex present?
if (regexScript.findRegex.length === 0) {
toastr.warning(`This regex script will not work, but was saved anyway: A find regex isn't present.`);
toastr.warning('This regex script will not work, but was saved anyway: A find regex isn\'t present.');
}
// Is there someplace to place results?
if (regexScript.placement.length === 0) {
toastr.warning(`This regex script will not work, but was saved anyway: One "Affects" checkbox must be selected!`);
toastr.warning('This regex script will not work, but was saved anyway: One "Affects" checkbox must be selected!');
}
if (existingScriptIndex !== -1) {
@ -69,45 +69,45 @@ async function deleteRegexScript({ existingId }) {
}
async function loadRegexScripts() {
$("#saved_regex_scripts").empty();
$('#saved_regex_scripts').empty();
const scriptTemplate = $(await $.get("scripts/extensions/regex/scriptTemplate.html"));
const scriptTemplate = $(await $.get('scripts/extensions/regex/scriptTemplate.html'));
extension_settings.regex.forEach((script) => {
// Have to clone here
const scriptHtml = scriptTemplate.clone();
scriptHtml.attr('id', uuidv4());
scriptHtml.find('.regex_script_name').text(script.scriptName);
scriptHtml.find('.disable_regex').prop("checked", script.disabled ?? false)
scriptHtml.find('.disable_regex').prop('checked', script.disabled ?? false)
.on('input', function () {
script.disabled = !!$(this).prop("checked");
script.disabled = !!$(this).prop('checked');
saveSettingsDebounced();
});
scriptHtml.find('.regex-toggle-on').on('click', function () {
scriptHtml.find('.disable_regex').prop("checked", true).trigger('input');
scriptHtml.find('.disable_regex').prop('checked', true).trigger('input');
});
scriptHtml.find('.regex-toggle-off').on('click', function () {
scriptHtml.find('.disable_regex').prop("checked", false).trigger('input');
scriptHtml.find('.disable_regex').prop('checked', false).trigger('input');
});
scriptHtml.find('.edit_existing_regex').on('click', async function () {
await onRegexEditorOpenClick(scriptHtml.attr("id"));
await onRegexEditorOpenClick(scriptHtml.attr('id'));
});
scriptHtml.find('.delete_regex').on('click', async function () {
const confirm = await callPopup("Are you sure you want to delete this regex script?", "confirm");
const confirm = await callPopup('Are you sure you want to delete this regex script?', 'confirm');
if (!confirm) {
return;
}
await deleteRegexScript({ existingId: scriptHtml.attr("id") });
await deleteRegexScript({ existingId: scriptHtml.attr('id') });
});
$("#saved_regex_scripts").append(scriptHtml);
$('#saved_regex_scripts').append(scriptHtml);
});
}
async function onRegexEditorOpenClick(existingId) {
const editorHtml = $(await $.get("scripts/extensions/regex/editor.html"));
const editorHtml = $(await $.get('scripts/extensions/regex/editor.html'));
// If an ID exists, fill in all the values
let existingScriptIndex = -1;
@ -117,92 +117,92 @@ async function onRegexEditorOpenClick(existingId) {
if (existingScriptIndex !== -1) {
const existingScript = extension_settings.regex[existingScriptIndex];
if (existingScript.scriptName) {
editorHtml.find(`.regex_script_name`).val(existingScript.scriptName);
editorHtml.find('.regex_script_name').val(existingScript.scriptName);
} else {
toastr.error("This script doesn't have a name! Please delete it.")
toastr.error('This script doesn\'t have a name! Please delete it.')
return;
}
editorHtml.find(`.find_regex`).val(existingScript.findRegex || "");
editorHtml.find(`.regex_replace_string`).val(existingScript.replaceString || "");
editorHtml.find(`.regex_trim_strings`).val(existingScript.trimStrings?.join("\n") || []);
editorHtml.find('.find_regex').val(existingScript.findRegex || '');
editorHtml.find('.regex_replace_string').val(existingScript.replaceString || '');
editorHtml.find('.regex_trim_strings').val(existingScript.trimStrings?.join('\n') || []);
editorHtml
.find(`input[name="disabled"]`)
.prop("checked", existingScript.disabled ?? false);
.find('input[name="disabled"]')
.prop('checked', existingScript.disabled ?? false);
editorHtml
.find(`input[name="only_format_display"]`)
.prop("checked", existingScript.markdownOnly ?? false);
.find('input[name="only_format_display"]')
.prop('checked', existingScript.markdownOnly ?? false);
editorHtml
.find(`input[name="only_format_prompt"]`)
.prop("checked", existingScript.promptOnly ?? false);
.find('input[name="only_format_prompt"]')
.prop('checked', existingScript.promptOnly ?? false);
editorHtml
.find(`input[name="run_on_edit"]`)
.prop("checked", existingScript.runOnEdit ?? false);
.find('input[name="run_on_edit"]')
.prop('checked', existingScript.runOnEdit ?? false);
editorHtml
.find(`input[name="substitute_regex"]`)
.prop("checked", existingScript.substituteRegex ?? false);
.find('input[name="substitute_regex"]')
.prop('checked', existingScript.substituteRegex ?? false);
editorHtml
.find(`select[name="replace_strategy_select"]`)
.find('select[name="replace_strategy_select"]')
.val(existingScript.replaceStrategy ?? 0);
existingScript.placement.forEach((element) => {
editorHtml
.find(`input[name="replace_position"][value="${element}"]`)
.prop("checked", true);
.prop('checked', true);
});
}
} else {
editorHtml
.find(`input[name="only_format_display"]`)
.prop("checked", true);
.find('input[name="only_format_display"]')
.prop('checked', true);
editorHtml
.find(`input[name="run_on_edit"]`)
.prop("checked", true);
.find('input[name="run_on_edit"]')
.prop('checked', true);
editorHtml
.find(`input[name="replace_position"][value="1"]`)
.prop("checked", true);
.find('input[name="replace_position"][value="1"]')
.prop('checked', true);
}
const popupResult = await callPopup(editorHtml, "confirm", undefined, { okButton: "Save" });
const popupResult = await callPopup(editorHtml, 'confirm', undefined, { okButton: 'Save' });
if (popupResult) {
const newRegexScript = {
scriptName: editorHtml.find(".regex_script_name").val(),
findRegex: editorHtml.find(".find_regex").val(),
replaceString: editorHtml.find(".regex_replace_string").val(),
trimStrings: editorHtml.find(".regex_trim_strings").val().split("\n").filter((e) => e.length !== 0) || [],
scriptName: editorHtml.find('.regex_script_name').val(),
findRegex: editorHtml.find('.find_regex').val(),
replaceString: editorHtml.find('.regex_replace_string').val(),
trimStrings: editorHtml.find('.regex_trim_strings').val().split('\n').filter((e) => e.length !== 0) || [],
placement:
editorHtml
.find(`input[name="replace_position"]`)
.filter(":checked")
.find('input[name="replace_position"]')
.filter(':checked')
.map(function () { return parseInt($(this).val()) })
.get()
.filter((e) => !isNaN(e)) || [],
disabled:
editorHtml
.find(`input[name="disabled"]`)
.prop("checked"),
.find('input[name="disabled"]')
.prop('checked'),
markdownOnly:
editorHtml
.find(`input[name="only_format_display"]`)
.prop("checked"),
.find('input[name="only_format_display"]')
.prop('checked'),
promptOnly:
editorHtml
.find(`input[name="only_format_prompt"]`)
.prop("checked"),
.find('input[name="only_format_prompt"]')
.prop('checked'),
runOnEdit:
editorHtml
.find(`input[name="run_on_edit"]`)
.prop("checked"),
.find('input[name="run_on_edit"]')
.prop('checked'),
substituteRegex:
editorHtml
.find(`input[name="substitute_regex"]`)
.prop("checked"),
.find('input[name="substitute_regex"]')
.prop('checked'),
replaceStrategy:
parseInt(editorHtml
.find(`select[name="replace_strategy_select"]`)
.find(`:selected`)
.find('select[name="replace_strategy_select"]')
.find(':selected')
.val()) ?? 0
};
@ -252,7 +252,7 @@ function migrateSettings() {
*/
function runRegexCallback(args, value) {
if (!args.name) {
toastr.warning("No regex script name provided.");
toastr.warning('No regex script name provided.');
return value;
}
@ -282,13 +282,13 @@ jQuery(async () => {
}
// Manually disable the extension since static imports auto-import the JS file
if (extension_settings.disabledExtensions.includes("regex")) {
if (extension_settings.disabledExtensions.includes('regex')) {
return;
}
const settingsHtml = await $.get("scripts/extensions/regex/dropdown.html");
$("#extensions_settings2").append(settingsHtml);
$("#open_regex_editor").on("click", function () {
const settingsHtml = await $.get('scripts/extensions/regex/dropdown.html');
$('#extensions_settings2').append(settingsHtml);
$('#open_regex_editor').on('click', function () {
onRegexEditorOpenClick(false);
});
@ -297,7 +297,7 @@ jQuery(async () => {
stop: function () {
let newScripts = [];
$('#saved_regex_scripts').children().each(function () {
const scriptName = $(this).find(".regex_script_name").text();
const scriptName = $(this).find('.regex_script_name').text();
const existingScript = extension_settings.regex.find((e) => e.scriptName === scriptName);
if (existingScript) {
newScripts.push(existingScript);
@ -307,13 +307,13 @@ jQuery(async () => {
extension_settings.regex = newScripts;
saveSettingsDebounced();
console.debug("Regex scripts reordered");
console.debug('Regex scripts reordered');
// TODO: Maybe reload regex scripts after move
},
});
await loadRegexScripts();
$("#saved_regex_scripts").sortable("enable");
$('#saved_regex_scripts').sortable('enable');
registerSlashCommand('regex', runRegexCallback, [], '(name=scriptName [input]) runs a Regex extension script by name on the provided string. The script must be enabled.', true, true);
});

View File

@ -1,7 +1,7 @@
import { getRequestHeaders } from "../../script.js";
import { extension_settings } from "../extensions.js";
import { SECRET_KEYS, secret_state } from "../secrets.js";
import { createThumbnail } from "../utils.js";
import { getRequestHeaders } from '../../script.js';
import { extension_settings } from '../extensions.js';
import { SECRET_KEYS, secret_state } from '../secrets.js';
import { createThumbnail } from '../utils.js';
/**
* Generates a caption for an image using a multimodal model.

View File

@ -16,14 +16,14 @@ import {
user_avatar,
getCharacterAvatar,
formatCharacterAvatar,
} from "../../../script.js";
import { getApiUrl, getContext, extension_settings, doExtrasFetch, modules, renderExtensionTemplate } from "../../extensions.js";
import { selected_group } from "../../group-chats.js";
import { stringFormat, initScrollHeight, resetScrollHeight, getCharaFilename, saveBase64AsFile, getBase64Async, delay } from "../../utils.js";
import { getMessageTimeStamp, humanizedDateTime } from "../../RossAscends-mods.js";
import { SECRET_KEYS, secret_state } from "../../secrets.js";
import { getNovelUnlimitedImageGeneration, getNovelAnlas, loadNovelSubscriptionData } from "../../nai-settings.js";
import { getMultimodalCaption } from "../shared.js";
} from '../../../script.js';
import { getApiUrl, getContext, extension_settings, doExtrasFetch, modules, renderExtensionTemplate } from '../../extensions.js';
import { selected_group } from '../../group-chats.js';
import { stringFormat, initScrollHeight, resetScrollHeight, getCharaFilename, saveBase64AsFile, getBase64Async, delay } from '../../utils.js';
import { getMessageTimeStamp, humanizedDateTime } from '../../RossAscends-mods.js';
import { SECRET_KEYS, secret_state } from '../../secrets.js';
import { getNovelUnlimitedImageGeneration, getNovelAnlas, loadNovelSubscriptionData } from '../../nai-settings.js';
import { getMultimodalCaption } from '../shared.js';
export { MODULE_NAME };
// Wraps a string into monospace font-face span
@ -103,12 +103,12 @@ const messageTrigger = {
const promptTemplates = {
/*OLD: [generationMode.CHARACTER]: "Pause your roleplay and provide comma-delimited list of phrases and keywords which describe {{char}}'s physical appearance and clothing. Ignore {{char}}'s personality traits, and chat history when crafting this description. End your response once the comma-delimited list is complete. Do not roleplay when writing this description, and do not attempt to continue the story.", */
[generationMode.CHARACTER]: "[In the next response I want you to provide only a detailed comma-delimited list of keywords and phrases which describe {{char}}. The list must include all of the following items in this order: name, species and race, gender, age, clothing, occupation, physical features and appearances. Do not include descriptions of non-visual qualities such as personality, movements, scents, mental traits, or anything which could not be seen in a still photograph. Do not write in full sentences. Prefix your description with the phrase 'full body portrait,']",
[generationMode.CHARACTER]: '[In the next response I want you to provide only a detailed comma-delimited list of keywords and phrases which describe {{char}}. The list must include all of the following items in this order: name, species and race, gender, age, clothing, occupation, physical features and appearances. Do not include descriptions of non-visual qualities such as personality, movements, scents, mental traits, or anything which could not be seen in a still photograph. Do not write in full sentences. Prefix your description with the phrase \'full body portrait,\']',
//face-specific prompt
[generationMode.FACE]: "[In the next response I want you to provide only a detailed comma-delimited list of keywords and phrases which describe {{char}}. The list must include all of the following items in this order: name, species and race, gender, age, facial features and expressions, occupation, hair and hair accessories (if any), what they are wearing on their upper body (if anything). Do not describe anything below their neck. Do not include descriptions of non-visual qualities such as personality, movements, scents, mental traits, or anything which could not be seen in a still photograph. Do not write in full sentences. Prefix your description with the phrase 'close up facial portrait,']",
[generationMode.FACE]: '[In the next response I want you to provide only a detailed comma-delimited list of keywords and phrases which describe {{char}}. The list must include all of the following items in this order: name, species and race, gender, age, facial features and expressions, occupation, hair and hair accessories (if any), what they are wearing on their upper body (if anything). Do not describe anything below their neck. Do not include descriptions of non-visual qualities such as personality, movements, scents, mental traits, or anything which could not be seen in a still photograph. Do not write in full sentences. Prefix your description with the phrase \'close up facial portrait,\']',
//prompt for only the last message
[generationMode.USER]: "[Pause your roleplay and provide a detailed description of {{user}}'s physical appearance from the perspective of {{char}} in the form of a comma-delimited list of keywords and phrases. The list must include all of the following items in this order: name, species and race, gender, age, clothing, occupation, physical features and appearances. Do not include descriptions of non-visual qualities such as personality, movements, scents, mental traits, or anything which could not be seen in a still photograph. Do not write in full sentences. Prefix your description with the phrase 'full body portrait,'. Ignore the rest of the story when crafting this description. Do not roleplay as {{char}} when writing this description, and do not attempt to continue the story.]",
[generationMode.SCENARIO]: "[Pause your roleplay and provide a detailed description for all of the following: a brief recap of recent events in the story, {{char}}'s appearance, and {{char}}'s surroundings. Do not roleplay while writing this description.]",
[generationMode.USER]: '[Pause your roleplay and provide a detailed description of {{user}}\'s physical appearance from the perspective of {{char}} in the form of a comma-delimited list of keywords and phrases. The list must include all of the following items in this order: name, species and race, gender, age, clothing, occupation, physical features and appearances. Do not include descriptions of non-visual qualities such as personality, movements, scents, mental traits, or anything which could not be seen in a still photograph. Do not write in full sentences. Prefix your description with the phrase \'full body portrait,\'. Ignore the rest of the story when crafting this description. Do not roleplay as {{char}} when writing this description, and do not attempt to continue the story.]',
[generationMode.SCENARIO]: '[Pause your roleplay and provide a detailed description for all of the following: a brief recap of recent events in the story, {{char}}\'s appearance, and {{char}}\'s surroundings. Do not roleplay while writing this description.]',
[generationMode.NOW]: `[Pause your roleplay. Your next response must be formatted as a single comma-delimited list of concise keywords. The list will describe of the visual details included in the last chat message.
@ -134,16 +134,16 @@ const promptTemplates = {
A correctly formatted example response would be:
'(location),(character list by gender),(primary action), (relative character position) POV, (character 1's description and actions), (character 2's description and actions)']`,
[generationMode.RAW_LAST]: "[Pause your roleplay and provide ONLY the last chat message string back to me verbatim. Do not write anything after the string. Do not roleplay at all in your response. Do not continue the roleplay story.]",
[generationMode.BACKGROUND]: "[Pause your roleplay and provide a detailed description of {{char}}'s surroundings in the form of a comma-delimited list of keywords and phrases. The list must include all of the following items in this order: location, time of day, weather, lighting, and any other relevant details. Do not include descriptions of characters and non-visual qualities such as names, personality, movements, scents, mental traits, or anything which could not be seen in a still photograph. Do not write in full sentences. Prefix your description with the phrase 'background,'. Ignore the rest of the story when crafting this description. Do not roleplay as {{user}} when writing this description, and do not attempt to continue the story.]",
[generationMode.FACE_MULTIMODAL]: `Provide an exhaustive comma-separated list of tags describing the appearance of the character on this image in great detail. Start with "close-up portrait".`,
[generationMode.CHARACTER_MULTIMODAL]: `Provide an exhaustive comma-separated list of tags describing the appearance of the character on this image in great detail. Start with "full body portrait".`,
[generationMode.USER_MULTIMODAL]: `Provide an exhaustive comma-separated list of tags describing the appearance of the character on this image in great detail. Start with "full body portrait".`,
[generationMode.RAW_LAST]: '[Pause your roleplay and provide ONLY the last chat message string back to me verbatim. Do not write anything after the string. Do not roleplay at all in your response. Do not continue the roleplay story.]',
[generationMode.BACKGROUND]: '[Pause your roleplay and provide a detailed description of {{char}}\'s surroundings in the form of a comma-delimited list of keywords and phrases. The list must include all of the following items in this order: location, time of day, weather, lighting, and any other relevant details. Do not include descriptions of characters and non-visual qualities such as names, personality, movements, scents, mental traits, or anything which could not be seen in a still photograph. Do not write in full sentences. Prefix your description with the phrase \'background,\'. Ignore the rest of the story when crafting this description. Do not roleplay as {{user}} when writing this description, and do not attempt to continue the story.]',
[generationMode.FACE_MULTIMODAL]: 'Provide an exhaustive comma-separated list of tags describing the appearance of the character on this image in great detail. Start with "close-up portrait".',
[generationMode.CHARACTER_MULTIMODAL]: 'Provide an exhaustive comma-separated list of tags describing the appearance of the character on this image in great detail. Start with "full body portrait".',
[generationMode.USER_MULTIMODAL]: 'Provide an exhaustive comma-separated list of tags describing the appearance of the character on this image in great detail. Start with "full body portrait".',
}
const helpString = [
`${m('(argument)')} requests to generate an image. Supported arguments: ${m(j(Object.values(triggerWords).flat()))}.`,
`Anything else would trigger a "free mode" to make generate whatever you prompted. Example: '/imagine apple tree' would generate a picture of an apple tree.`,
'Anything else would trigger a "free mode" to make generate whatever you prompted. Example: \'/imagine apple tree\' would generate a picture of an apple tree.',
].join(' ');
const defaultPrefix = 'best quality, absurdres, aesthetic,';
@ -680,7 +680,7 @@ const resolutionOptions = {
};
function onResolutionChange() {
const selectedOption = $("#sd_resolution").val();
const selectedOption = $('#sd_resolution').val();
const selectedResolution = resolutionOptions[selectedOption];
if (!selectedResolution) {
@ -688,8 +688,8 @@ function onResolutionChange() {
return;
}
$("#sd_height").val(selectedResolution.height).trigger('input');
$("#sd_width").val(selectedResolution.width).trigger('input');
$('#sd_height').val(selectedResolution.height).trigger('input');
$('#sd_width').val(selectedResolution.width).trigger('input');
}
function onSchedulerChange() {
@ -883,7 +883,7 @@ async function validateComfyUrl() {
throw new Error('URL is not set.');
}
const result = await fetch(`/api/sd/comfy/ping`, {
const result = await fetch('/api/sd/comfy/ping', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
@ -1158,7 +1158,7 @@ async function loadComfySamplers() {
}
try {
const result = await fetch(`/api/sd/comfy/samplers`, {
const result = await fetch('/api/sd/comfy/samplers', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
@ -1383,7 +1383,7 @@ async function loadComfyModels() {
}
try {
const result = await fetch(`/api/sd/comfy/models`, {
const result = await fetch('/api/sd/comfy/models', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
@ -1442,7 +1442,7 @@ async function loadComfySchedulers() {
}
try {
const result = await fetch(`/api/sd/comfy/schedulers`, {
const result = await fetch('/api/sd/comfy/schedulers', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
@ -1501,7 +1501,7 @@ async function loadComfyVaes() {
}
try {
const result = await fetch(`/api/sd/comfy/vaes`, {
const result = await fetch('/api/sd/comfy/vaes', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
@ -1524,7 +1524,7 @@ async function loadComfyWorkflows() {
try {
$('#sd_comfy_workflow').empty();
const result = await fetch(`/api/sd/comfy/workflows`, {
const result = await fetch('/api/sd/comfy/workflows', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
@ -1624,7 +1624,7 @@ async function generatePicture(_, trigger, message, callback) {
}
if (!isValidState()) {
toastr.warning("Extensions API is not connected or doesn't provide SD module. Enable Stable Horde to generate images.");
toastr.warning('Extensions API is not connected or doesn\'t provide SD module. Enable Stable Horde to generate images.');
return;
}
@ -2140,7 +2140,7 @@ async function generateComfyImage(prompt) {
console.log(`{
"prompt": ${workflow}
}`);
const promptResult = await fetch(`/api/sd/comfy/generate`, {
const promptResult = await fetch('/api/sd/comfy/generate', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
@ -2154,7 +2154,7 @@ async function generateComfyImage(prompt) {
}
async function onComfyOpenWorkflowEditorClick() {
let workflow = await (await fetch(`/api/sd/comfy/workflow`, {
let workflow = await (await fetch('/api/sd/comfy/workflow', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
@ -2162,7 +2162,7 @@ async function onComfyOpenWorkflowEditorClick() {
}),
})).json();
const editorHtml = $(await $.get('scripts/extensions/stable-diffusion/comfyWorkflowEditor.html'));
const popupResult = callPopup(editorHtml, "confirm", undefined, { okButton: "Save", wide: true, large: true, rows: 1 });
const popupResult = callPopup(editorHtml, 'confirm', undefined, { okButton: 'Save', wide: true, large: true, rows: 1 });
const checkPlaceholders = () => {
workflow = $('#sd_comfy_workflow_editor_workflow').val().toString();
$('.sd_comfy_workflow_editor_placeholder_list > li[data-placeholder]').each(function (idx) {
@ -2176,7 +2176,7 @@ async function onComfyOpenWorkflowEditorClick() {
checkPlaceholders();
$('#sd_comfy_workflow_editor_workflow').on('input', checkPlaceholders);
if (await popupResult) {
const response = await fetch(`/api/sd/comfy/save-workflow`, {
const response = await fetch('/api/sd/comfy/save-workflow', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
@ -2200,7 +2200,7 @@ async function onComfyNewWorkflowClick() {
name += '.json';
}
extension_settings.sd.comfy_workflow = name;
const response = await fetch(`/api/sd/comfy/save-workflow`, {
const response = await fetch('/api/sd/comfy/save-workflow', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
@ -2290,7 +2290,7 @@ function addSDGenButtons() {
const messageButton = $('.sd_message_gen');
const button = $('#sd_gen');
const waitButton = $("#sd_gen_wait");
const waitButton = $('#sd_gen_wait');
const dropdown = $('#sd_dropdown');
waitButton.hide();
dropdown.hide();
@ -2306,7 +2306,7 @@ function addSDGenButtons() {
$(document).on('click touchend', function (e) {
const target = $(e.target);
if (target.is(dropdown)) return;
if (target.is(button) && !dropdown.is(":visible") && $("#send_but").is(":visible")) {
if (target.is(button) && !dropdown.is(':visible') && $('#send_but').is(':visible')) {
e.preventDefault();
dropdown.fadeIn(animation_duration);
@ -2385,7 +2385,7 @@ async function sdMessageButton(e) {
await sendGenerationRequest(generationType, prompt, characterFileName, saveGeneratedImage);
}
else {
console.log("doing /sd raw last");
console.log('doing /sd raw last');
await generatePicture('sd', 'raw_last', messageText, saveGeneratedImage);
}
}
@ -2417,22 +2417,22 @@ async function sdMessageButton(e) {
}
}
$("#sd_dropdown [id]").on("click", function () {
const id = $(this).attr("id");
$('#sd_dropdown [id]').on('click', function () {
const id = $(this).attr('id');
const idParamMap = {
"sd_you": "you",
"sd_face": "face",
"sd_me": "me",
"sd_world": "scene",
"sd_last": "last",
"sd_raw_last": "raw_last",
"sd_background": "background"
'sd_you': 'you',
'sd_face': 'face',
'sd_me': 'me',
'sd_world': 'scene',
'sd_last': 'last',
'sd_raw_last': 'raw_last',
'sd_background': 'background'
};
const param = idParamMap[id];
if (param) {
console.log("doing /sd " + param)
console.log('doing /sd ' + param)
generatePicture('sd', param);
}
});
@ -2489,9 +2489,9 @@ jQuery(async () => {
$('#sd_multimodal_captioning').on('input', onMultimodalCaptioningInput);
$('.sd_settings .inline-drawer-toggle').on('click', function () {
initScrollHeight($("#sd_prompt_prefix"));
initScrollHeight($("#sd_negative_prompt"));
initScrollHeight($("#sd_character_prompt"));
initScrollHeight($('#sd_prompt_prefix'));
initScrollHeight($('#sd_negative_prompt'));
initScrollHeight($('#sd_character_prompt'));
})
for (const [key, value] of Object.entries(resolutionOptions)) {

View File

@ -1,15 +1,15 @@
import { callPopup, main_api } from "../../../script.js";
import { getContext } from "../../extensions.js";
import { registerSlashCommand } from "../../slash-commands.js";
import { getFriendlyTokenizerName, getTextTokens, getTokenCount, tokenizers } from "../../tokenizers.js";
import { resetScrollHeight } from "../../utils.js";
import { callPopup, main_api } from '../../../script.js';
import { getContext } from '../../extensions.js';
import { registerSlashCommand } from '../../slash-commands.js';
import { getFriendlyTokenizerName, getTextTokens, getTokenCount, tokenizers } from '../../tokenizers.js';
import { resetScrollHeight } from '../../utils.js';
function rgb2hex(rgb) {
rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
return (rgb && rgb.length === 4) ? "#" +
("0" + parseInt(rgb[1], 10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2], 10).toString(16)).slice(-2) +
("0" + parseInt(rgb[3], 10).toString(16)).slice(-2) : '';
return (rgb && rgb.length === 4) ? '#' +
('0' + parseInt(rgb[1], 10).toString(16)).slice(-2) +
('0' + parseInt(rgb[2], 10).toString(16)).slice(-2) +
('0' + parseInt(rgb[3], 10).toString(16)).slice(-2) : '';
}
$('button').click(function () {

View File

@ -9,9 +9,9 @@ import {
saveSettingsDebounced,
substituteParams,
updateMessageBlock,
} from "../../../script.js";
import { extension_settings, getContext } from "../../extensions.js";
import { secret_state, writeSecret } from "../../secrets.js";
} from '../../../script.js';
import { extension_settings, getContext } from '../../extensions.js';
import { secret_state, writeSecret } from '../../secrets.js';
export const autoModeOptions = {
NONE: 'none',
@ -143,10 +143,10 @@ const LOCAL_URL = ['libre', 'oneringtranslator', 'deeplx'];
function showKeysButton() {
const providerRequiresKey = KEY_REQUIRED.includes(extension_settings.translate.provider);
const providerOptionalUrl = LOCAL_URL.includes(extension_settings.translate.provider);
$("#translate_key_button").toggle(providerRequiresKey);
$("#translate_key_button").toggleClass('success', Boolean(secret_state[extension_settings.translate.provider]));
$("#translate_url_button").toggle(providerOptionalUrl);
$("#translate_url_button").toggleClass('success', Boolean(secret_state[extension_settings.translate.provider + "_url"]));
$('#translate_key_button').toggle(providerRequiresKey);
$('#translate_key_button').toggleClass('success', Boolean(secret_state[extension_settings.translate.provider]));
$('#translate_url_button').toggle(providerOptionalUrl);
$('#translate_url_button').toggleClass('success', Boolean(secret_state[extension_settings.translate.provider + '_url']));
}
function loadSettings() {
@ -164,7 +164,7 @@ function loadSettings() {
async function translateImpersonate(text) {
const translatedText = await translate(text, extension_settings.translate.target_language);
$("#send_textarea").val(translatedText);
$('#send_textarea').val(translatedText);
}
async function translateIncomingMessage(messageId) {
@ -540,7 +540,7 @@ jQuery(() => {
await writeSecret(extension_settings.translate.provider, key);
toastr.success('API Key saved');
$("#translate_key_button").addClass('success');
$('#translate_key_button').addClass('success');
});
$('#translate_url_button').on('click', async () => {
const optionText = $('#translation_provider option:selected').text();
@ -556,9 +556,9 @@ jQuery(() => {
return;
}
await writeSecret(extension_settings.translate.provider + "_url", url);
await writeSecret(extension_settings.translate.provider + '_url', url);
toastr.success('API URL saved');
$("#translate_url_button").addClass('success');
$('#translate_url_button').addClass('success');
});
loadSettings();

View File

@ -4,13 +4,13 @@ TODO:
- Delete useless call
*/
import { doExtrasFetch, extension_settings, getApiUrl, modules } from "../../extensions.js"
import { callPopup } from "../../../script.js"
import { initVoiceMap } from "./index.js"
import { doExtrasFetch, extension_settings, getApiUrl, modules } from '../../extensions.js'
import { callPopup } from '../../../script.js'
import { initVoiceMap } from './index.js'
export { CoquiTtsProvider }
const DEBUG_PREFIX = "<Coqui TTS module> ";
const DEBUG_PREFIX = '<Coqui TTS module> ';
let inApiCall = false;
let coquiApiModels = {}; // Initialized only once
@ -33,24 +33,24 @@ coquiApiModels format [language][dataset][name]:coqui-api-model-id, example:
}
*/
const languageLabels = {
"multilingual": "Multilingual",
"en": "English",
"fr": "French",
"es": "Spanish",
"ja": "Japanese"
'multilingual': 'Multilingual',
'en': 'English',
'fr': 'French',
'es': 'Spanish',
'ja': 'Japanese'
}
function throwIfModuleMissing() {
if (!modules.includes('coqui-tts')) {
const message = `Coqui TTS module not loaded. Add coqui-tts to enable-modules and restart the Extras API.`
const message = 'Coqui TTS module not loaded. Add coqui-tts to enable-modules and restart the Extras API.'
// toastr.error(message, { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
throw new Error(DEBUG_PREFIX, message);
}
}
function resetModelSettings() {
$("#coqui_api_model_settings_language").val("none");
$("#coqui_api_model_settings_speaker").val("none");
$('#coqui_api_model_settings_language').val('none');
$('#coqui_api_model_settings_speaker').val('none');
}
class CoquiTtsProvider {
@ -138,29 +138,29 @@ class CoquiTtsProvider {
await initLocalModels();
this.updateCustomVoices(); // Overide any manual modification
$("#coqui_api_model_div").hide();
$("#coqui_local_model_div").hide();
$('#coqui_api_model_div').hide();
$('#coqui_local_model_div').hide();
$("#coqui_api_language").show();
$("#coqui_api_model_name").hide();
$("#coqui_api_model_settings").hide();
$("#coqui_api_model_install_status").hide();
$("#coqui_api_model_install_button").hide();
$('#coqui_api_language').show();
$('#coqui_api_model_name').hide();
$('#coqui_api_model_settings').hide();
$('#coqui_api_model_install_status').hide();
$('#coqui_api_model_install_button').hide();
let that = this
$("#coqui_model_origin").on("change", function () { that.onModelOriginChange() });
$("#coqui_api_language").on("change", function () { that.onModelLanguageChange() });
$("#coqui_api_model_name").on("change", function () { that.onModelNameChange() });
$('#coqui_model_origin').on('change', function () { that.onModelOriginChange() });
$('#coqui_api_language').on('change', function () { that.onModelLanguageChange() });
$('#coqui_api_model_name').on('change', function () { that.onModelNameChange() });
$("#coqui_remove_voiceId_mapping").on("click", function () { that.onRemoveClick() });
$("#coqui_add_voiceId_mapping").on("click", function () { that.onAddClick() });
$('#coqui_remove_voiceId_mapping').on('click', function () { that.onRemoveClick() });
$('#coqui_add_voiceId_mapping').on('click', function () { that.onAddClick() });
// Load coqui-api settings from json file
await fetch("/scripts/extensions/tts/coqui_api_models_settings.json")
await fetch('/scripts/extensions/tts/coqui_api_models_settings.json')
.then(response => response.json())
.then(json => {
coquiApiModels = json;
console.debug(DEBUG_PREFIX,"initialized coqui-api model list to", coquiApiModels);
console.debug(DEBUG_PREFIX,'initialized coqui-api model list to', coquiApiModels);
/*
$('#coqui_api_language')
.find('option')
@ -176,11 +176,11 @@ class CoquiTtsProvider {
});
// Load coqui-api FULL settings from json file
await fetch("/scripts/extensions/tts/coqui_api_models_settings_full.json")
await fetch('/scripts/extensions/tts/coqui_api_models_settings_full.json')
.then(response => response.json())
.then(json => {
coquiApiModelsFull = json;
console.debug(DEBUG_PREFIX,"initialized coqui-api full model list to", coquiApiModelsFull);
console.debug(DEBUG_PREFIX,'initialized coqui-api full model list to', coquiApiModelsFull);
/*
$('#coqui_api_full_language')
.find('option')
@ -207,17 +207,17 @@ class CoquiTtsProvider {
this.settings.customVoices = {};
for (let voiceName in this.settings.voiceMapDict) {
const voiceId = this.settings.voiceMapDict[voiceName];
this.settings.customVoices[voiceName] = voiceId["model_id"];
this.settings.customVoices[voiceName] = voiceId['model_id'];
if (voiceId["model_language"] != null)
this.settings.customVoices[voiceName] += "[" + voiceId["model_language"] + "]";
if (voiceId['model_language'] != null)
this.settings.customVoices[voiceName] += '[' + voiceId['model_language'] + ']';
if (voiceId["model_speaker"] != null)
this.settings.customVoices[voiceName] += "[" + voiceId["model_speaker"] + "]";
if (voiceId['model_speaker'] != null)
this.settings.customVoices[voiceName] += '[' + voiceId['model_speaker'] + ']';
}
// Update UI select list with voices
$("#coqui_voicename_select").empty()
$('#coqui_voicename_select').empty()
$('#coqui_voicename_select')
.find('option')
.remove()
@ -225,14 +225,14 @@ class CoquiTtsProvider {
.append('<option value="none">Select Voice</option>')
.val('none')
for (const voiceName in this.settings.voiceMapDict) {
$("#coqui_voicename_select").append(new Option(voiceName, voiceName));
$('#coqui_voicename_select').append(new Option(voiceName, voiceName));
}
this.onSettingsChange()
}
onSettingsChange() {
console.debug(DEBUG_PREFIX, "Settings changes", this.settings);
console.debug(DEBUG_PREFIX, 'Settings changes', this.settings);
extension_settings.tts.Coqui = this.settings;
}
@ -248,92 +248,92 @@ class CoquiTtsProvider {
// Ask user for voiceId name to save voice
const voiceName = await callPopup('<h3>Name of Coqui voice to add to voice select dropdown:</h3>', 'input')
const model_origin = $("#coqui_model_origin").val();
const model_language = $("#coqui_api_language").val();
const model_name = $("#coqui_api_model_name").val();
let model_setting_language = $("#coqui_api_model_settings_language").val();
let model_setting_speaker = $("#coqui_api_model_settings_speaker").val();
const model_origin = $('#coqui_model_origin').val();
const model_language = $('#coqui_api_language').val();
const model_name = $('#coqui_api_model_name').val();
let model_setting_language = $('#coqui_api_model_settings_language').val();
let model_setting_speaker = $('#coqui_api_model_settings_speaker').val();
if (!voiceName) {
toastr.error(`Voice name empty, please enter one.`, DEBUG_PREFIX + " voice mapping voice name", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
toastr.error('Voice name empty, please enter one.', DEBUG_PREFIX + ' voice mapping voice name', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
this.updateCustomVoices(); // Overide any manual modification
return;
}
if (model_origin == "none") {
toastr.error(`Origin not selected, please select one.`, DEBUG_PREFIX + " voice mapping origin", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
if (model_origin == 'none') {
toastr.error('Origin not selected, please select one.', DEBUG_PREFIX + ' voice mapping origin', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
this.updateCustomVoices(); // Overide any manual modification
return;
}
if (model_origin == "local") {
const model_id = $("#coqui_local_model_name").val();
if (model_origin == 'local') {
const model_id = $('#coqui_local_model_name').val();
if (model_name == "none") {
toastr.error(`Model not selected, please select one.`, DEBUG_PREFIX + " voice mapping model", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
if (model_name == 'none') {
toastr.error('Model not selected, please select one.', DEBUG_PREFIX + ' voice mapping model', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
this.updateCustomVoices(); // Overide any manual modification
return;
}
this.settings.voiceMapDict[voiceName] = { model_type: "local", model_id: "local/" + model_id };
console.debug(DEBUG_PREFIX, "Registered new voice map: ", voiceName, ":", this.settings.voiceMapDict[voiceName]);
this.settings.voiceMapDict[voiceName] = { model_type: 'local', model_id: 'local/' + model_id };
console.debug(DEBUG_PREFIX, 'Registered new voice map: ', voiceName, ':', this.settings.voiceMapDict[voiceName]);
this.updateCustomVoices(); // Overide any manual modification
return;
}
if (model_language == "none") {
toastr.error(`Language not selected, please select one.`, DEBUG_PREFIX + " voice mapping language", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
if (model_language == 'none') {
toastr.error('Language not selected, please select one.', DEBUG_PREFIX + ' voice mapping language', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
this.updateCustomVoices(); // Overide any manual modification
return;
}
if (model_name == "none") {
toastr.error(`Model not selected, please select one.`, DEBUG_PREFIX + " voice mapping model", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
if (model_name == 'none') {
toastr.error('Model not selected, please select one.', DEBUG_PREFIX + ' voice mapping model', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
this.updateCustomVoices(); // Overide any manual modification
return;
}
if (model_setting_language == "none")
if (model_setting_language == 'none')
model_setting_language = null;
if (model_setting_speaker == "none")
if (model_setting_speaker == 'none')
model_setting_speaker = null;
const tokens = $('#coqui_api_model_name').val().split("/");
const tokens = $('#coqui_api_model_name').val().split('/');
const model_dataset = tokens[0];
const model_label = tokens[1];
const model_id = "tts_models/" + model_language + "/" + model_dataset + "/" + model_label
const model_id = 'tts_models/' + model_language + '/' + model_dataset + '/' + model_label
let modelDict = coquiApiModels
if (model_origin == "coqui-api-full")
if (model_origin == 'coqui-api-full')
modelDict = coquiApiModelsFull
if (model_setting_language == null & "languages" in modelDict[model_language][model_dataset][model_label]) {
toastr.error(`Model language not selected, please select one.`, DEBUG_PREFIX+" voice mapping model language", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
if (model_setting_language == null & 'languages' in modelDict[model_language][model_dataset][model_label]) {
toastr.error('Model language not selected, please select one.', DEBUG_PREFIX+' voice mapping model language', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
return;
}
if (model_setting_speaker == null & "speakers" in modelDict[model_language][model_dataset][model_label]) {
toastr.error(`Model speaker not selected, please select one.`, DEBUG_PREFIX+" voice mapping model speaker", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
if (model_setting_speaker == null & 'speakers' in modelDict[model_language][model_dataset][model_label]) {
toastr.error('Model speaker not selected, please select one.', DEBUG_PREFIX+' voice mapping model speaker', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
return;
}
console.debug(DEBUG_PREFIX, "Current custom voices: ", this.settings.customVoices);
console.debug(DEBUG_PREFIX, 'Current custom voices: ', this.settings.customVoices);
this.settings.voiceMapDict[voiceName] = { model_type: "coqui-api", model_id: model_id, model_language: model_setting_language, model_speaker: model_setting_speaker };
this.settings.voiceMapDict[voiceName] = { model_type: 'coqui-api', model_id: model_id, model_language: model_setting_language, model_speaker: model_setting_speaker };
console.debug(DEBUG_PREFIX, "Registered new voice map: ", voiceName, ":", this.settings.voiceMapDict[voiceName]);
console.debug(DEBUG_PREFIX, 'Registered new voice map: ', voiceName, ':', this.settings.voiceMapDict[voiceName]);
this.updateCustomVoices();
initVoiceMap() // Update TTS extension voiceMap
let successMsg = voiceName + ":" + model_id;
let successMsg = voiceName + ':' + model_id;
if (model_setting_language != null)
successMsg += "[" + model_setting_language + "]";
successMsg += '[' + model_setting_language + ']';
if (model_setting_speaker != null)
successMsg += "[" + model_setting_speaker + "]";
toastr.info(successMsg, DEBUG_PREFIX + " voice map updated", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
successMsg += '[' + model_setting_speaker + ']';
toastr.info(successMsg, DEBUG_PREFIX + ' voice map updated', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
return
}
@ -350,10 +350,10 @@ class CoquiTtsProvider {
}
async onRemoveClick() {
const voiceName = $("#coqui_voicename_select").val();
const voiceName = $('#coqui_voicename_select').val();
if (voiceName === "none") {
toastr.error(`Voice not selected, please select one.`, DEBUG_PREFIX + " voice mapping voiceId", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
if (voiceName === 'none') {
toastr.error('Voice not selected, please select one.', DEBUG_PREFIX + ' voice mapping voiceId', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
return;
}
@ -368,14 +368,14 @@ class CoquiTtsProvider {
resetModelSettings();
const model_origin = $('#coqui_model_origin').val();
if (model_origin == "none") {
$("#coqui_local_model_div").hide();
$("#coqui_api_model_div").hide();
if (model_origin == 'none') {
$('#coqui_local_model_div').hide();
$('#coqui_api_model_div').hide();
}
// show coqui model selected list (SAFE)
if (model_origin == "coqui-api") {
$("#coqui_local_model_div").hide();
if (model_origin == 'coqui-api') {
$('#coqui_local_model_div').hide();
$('#coqui_api_language')
.find('option')
@ -388,16 +388,16 @@ class CoquiTtsProvider {
let languageLabel = language
if (language in languageLabels)
languageLabel = languageLabels[language]
$("#coqui_api_language").append(new Option(languageLabel,language));
console.log(DEBUG_PREFIX,"added language",languageLabel,"(",language,")");
$('#coqui_api_language').append(new Option(languageLabel,language));
console.log(DEBUG_PREFIX,'added language',languageLabel,'(',language,')');
}
$("#coqui_api_model_div").show();
$('#coqui_api_model_div').show();
}
// show coqui model full list (UNSAFE)
if (model_origin == "coqui-api-full") {
$("#coqui_local_model_div").hide();
if (model_origin == 'coqui-api-full') {
$('#coqui_local_model_div').hide();
$('#coqui_api_language')
.find('option')
@ -410,35 +410,35 @@ class CoquiTtsProvider {
let languageLabel = language
if (language in languageLabels)
languageLabel = languageLabels[language]
$("#coqui_api_language").append(new Option(languageLabel,language));
console.log(DEBUG_PREFIX,"added language",languageLabel,"(",language,")");
$('#coqui_api_language').append(new Option(languageLabel,language));
console.log(DEBUG_PREFIX,'added language',languageLabel,'(',language,')');
}
$("#coqui_api_model_div").show();
$('#coqui_api_model_div').show();
}
// show local model list
if (model_origin == "local") {
$("#coqui_api_model_div").hide();
$("#coqui_local_model_div").show();
if (model_origin == 'local') {
$('#coqui_api_model_div').hide();
$('#coqui_local_model_div').show();
}
}
async onModelLanguageChange() {
throwIfModuleMissing();
resetModelSettings();
$("#coqui_api_model_settings").hide();
$('#coqui_api_model_settings').hide();
const model_origin = $('#coqui_model_origin').val();
const model_language = $('#coqui_api_language').val();
console.debug(model_language);
if (model_language == "none") {
$("#coqui_api_model_name").hide();
if (model_language == 'none') {
$('#coqui_api_model_name').hide();
return;
}
$("#coqui_api_model_name").show();
$('#coqui_api_model_name').show();
$('#coqui_api_model_name')
.find('option')
.remove()
@ -447,45 +447,45 @@ class CoquiTtsProvider {
.val('none');
let modelDict = coquiApiModels
if (model_origin == "coqui-api-full")
if (model_origin == 'coqui-api-full')
modelDict = coquiApiModelsFull
for(let model_dataset in modelDict[model_language])
for(let model_name in modelDict[model_language][model_dataset]) {
const model_id = model_dataset + "/" + model_name
const model_label = model_name + " (" + model_dataset + " dataset)"
$("#coqui_api_model_name").append(new Option(model_label, model_id));
const model_id = model_dataset + '/' + model_name
const model_label = model_name + ' (' + model_dataset + ' dataset)'
$('#coqui_api_model_name').append(new Option(model_label, model_id));
}
}
async onModelNameChange() {
throwIfModuleMissing();
resetModelSettings();
$("#coqui_api_model_settings").hide();
$('#coqui_api_model_settings').hide();
const model_origin = $('#coqui_model_origin').val();
// No model selected
if ($('#coqui_api_model_name').val() == "none") {
$("#coqui_api_model_install_button").off('click');
$("#coqui_api_model_install_button").hide();
if ($('#coqui_api_model_name').val() == 'none') {
$('#coqui_api_model_install_button').off('click');
$('#coqui_api_model_install_button').hide();
return;
}
// Get languages and speakers options
const model_language = $('#coqui_api_language').val();
const tokens = $('#coqui_api_model_name').val().split("/");
const tokens = $('#coqui_api_model_name').val().split('/');
const model_dataset = tokens[0];
const model_name = tokens[1];
let modelDict = coquiApiModels
if (model_origin == "coqui-api-full")
if (model_origin == 'coqui-api-full')
modelDict = coquiApiModelsFull
const model_settings = modelDict[model_language][model_dataset][model_name]
if ("languages" in model_settings) {
$("#coqui_api_model_settings").show();
$("#coqui_api_model_settings_language").show();
if ('languages' in model_settings) {
$('#coqui_api_model_settings').show();
$('#coqui_api_model_settings_language').show();
$('#coqui_api_model_settings_language')
.find('option')
.remove()
@ -493,18 +493,18 @@ class CoquiTtsProvider {
.append('<option value="none">Select language</option>')
.val('none');
for (let i = 0; i < model_settings["languages"].length; i++) {
const language_label = JSON.stringify(model_settings["languages"][i]).replaceAll("\"", "");
$("#coqui_api_model_settings_language").append(new Option(language_label, i));
for (let i = 0; i < model_settings['languages'].length; i++) {
const language_label = JSON.stringify(model_settings['languages'][i]).replaceAll('"', '');
$('#coqui_api_model_settings_language').append(new Option(language_label, i));
}
}
else {
$("#coqui_api_model_settings_language").hide();
$('#coqui_api_model_settings_language').hide();
}
if ("speakers" in model_settings) {
$("#coqui_api_model_settings").show();
$("#coqui_api_model_settings_speaker").show();
if ('speakers' in model_settings) {
$('#coqui_api_model_settings').show();
$('#coqui_api_model_settings_speaker').show();
$('#coqui_api_model_settings_speaker')
.find('option')
.remove()
@ -512,75 +512,75 @@ class CoquiTtsProvider {
.append('<option value="none">Select speaker</option>')
.val('none');
for (let i = 0; i < model_settings["speakers"].length; i++) {
const speaker_label = JSON.stringify(model_settings["speakers"][i]).replaceAll("\"", "");
$("#coqui_api_model_settings_speaker").append(new Option(speaker_label, i));
for (let i = 0; i < model_settings['speakers'].length; i++) {
const speaker_label = JSON.stringify(model_settings['speakers'][i]).replaceAll('"', '');
$('#coqui_api_model_settings_speaker').append(new Option(speaker_label, i));
}
}
else {
$("#coqui_api_model_settings_speaker").hide();
$('#coqui_api_model_settings_speaker').hide();
}
$("#coqui_api_model_install_status").text("Requesting model to extras server...");
$("#coqui_api_model_install_status").show();
$('#coqui_api_model_install_status').text('Requesting model to extras server...');
$('#coqui_api_model_install_status').show();
// Check if already installed and propose to do it otherwise
const model_id = modelDict[model_language][model_dataset][model_name]["id"]
console.debug(DEBUG_PREFIX,"Check if model is already installed",model_id);
const model_id = modelDict[model_language][model_dataset][model_name]['id']
console.debug(DEBUG_PREFIX,'Check if model is already installed',model_id);
let result = await CoquiTtsProvider.checkmodel_state(model_id);
result = await result.json();
const model_state = result["model_state"];
const model_state = result['model_state'];
console.debug(DEBUG_PREFIX, " Model state:", model_state)
console.debug(DEBUG_PREFIX, ' Model state:', model_state)
if (model_state == "installed") {
$("#coqui_api_model_install_status").text("Model already installed on extras server");
$("#coqui_api_model_install_button").hide();
if (model_state == 'installed') {
$('#coqui_api_model_install_status').text('Model already installed on extras server');
$('#coqui_api_model_install_button').hide();
}
else {
let action = "download"
if (model_state == "corrupted") {
action = "repare"
let action = 'download'
if (model_state == 'corrupted') {
action = 'repare'
//toastr.error("Click install button to reinstall the model "+$("#coqui_api_model_name").find(":selected").text(), DEBUG_PREFIX+" corrupted model install", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
$("#coqui_api_model_install_status").text("Model found but incomplete try install again (maybe still downloading)"); // (remove and download again)
$('#coqui_api_model_install_status').text('Model found but incomplete try install again (maybe still downloading)'); // (remove and download again)
}
else {
toastr.info("Click download button to install the model " + $("#coqui_api_model_name").find(":selected").text(), DEBUG_PREFIX + " model not installed", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
$("#coqui_api_model_install_status").text("Model not found on extras server");
toastr.info('Click download button to install the model ' + $('#coqui_api_model_name').find(':selected').text(), DEBUG_PREFIX + ' model not installed', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
$('#coqui_api_model_install_status').text('Model not found on extras server');
}
const onModelNameChange_pointer = this.onModelNameChange;
$("#coqui_api_model_install_button").off("click").on("click", async function () {
$('#coqui_api_model_install_button').off('click').on('click', async function () {
try {
$("#coqui_api_model_install_status").text("Downloading model...");
$("#coqui_api_model_install_button").hide();
$('#coqui_api_model_install_status').text('Downloading model...');
$('#coqui_api_model_install_button').hide();
//toastr.info("For model "+model_id, DEBUG_PREFIX+" Started "+action, { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
let apiResult = await CoquiTtsProvider.installModel(model_id, action);
apiResult = await apiResult.json();
console.debug(DEBUG_PREFIX, "Response:", apiResult);
console.debug(DEBUG_PREFIX, 'Response:', apiResult);
if (apiResult["status"] == "done") {
$("#coqui_api_model_install_status").text("Model installed and ready to use!");
$("#coqui_api_model_install_button").hide();
if (apiResult['status'] == 'done') {
$('#coqui_api_model_install_status').text('Model installed and ready to use!');
$('#coqui_api_model_install_button').hide();
onModelNameChange_pointer();
}
if (apiResult["status"] == "downloading") {
toastr.error("Check extras console for progress", DEBUG_PREFIX + " already downloading", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
$("#coqui_api_model_install_status").text("Already downloading a model, check extras console!");
$("#coqui_api_model_install_button").show();
if (apiResult['status'] == 'downloading') {
toastr.error('Check extras console for progress', DEBUG_PREFIX + ' already downloading', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
$('#coqui_api_model_install_status').text('Already downloading a model, check extras console!');
$('#coqui_api_model_install_button').show();
}
} catch (error) {
console.error(error)
toastr.error(error, DEBUG_PREFIX + " error with model download", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
toastr.error(error, DEBUG_PREFIX + ' error with model download', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
onModelNameChange_pointer();
}
// will refresh model status
});
$("#coqui_api_model_install_button").show();
$('#coqui_api_model_install_button').show();
return;
}
@ -606,7 +606,7 @@ class CoquiTtsProvider {
'Cache-Control': 'no-cache'
},
body: JSON.stringify({
"model_id": model_id,
'model_id': model_id,
})
});
@ -630,8 +630,8 @@ class CoquiTtsProvider {
'Cache-Control': 'no-cache'
},
body: JSON.stringify({
"model_id": model_id,
"action": action
'model_id': model_id,
'action': action
})
});
@ -658,8 +658,8 @@ class CoquiTtsProvider {
'Cache-Control': 'no-cache'
},
body: JSON.stringify({
"model_id": "model_id",
"action": "action"
'model_id': 'model_id',
'action': 'action'
})
})
@ -683,18 +683,18 @@ class CoquiTtsProvider {
const url = new URL(getApiUrl());
url.pathname = '/api/text-to-speech/coqui/generate-tts';
let language = "none"
let speaker = "none"
const tokens = voiceId.replaceAll("]", "").replaceAll("\"", "").split("[");
let language = 'none'
let speaker = 'none'
const tokens = voiceId.replaceAll(']', '').replaceAll('"', '').split('[');
const model_id = tokens[0]
console.debug(DEBUG_PREFIX, "Preparing TTS request for", tokens)
console.debug(DEBUG_PREFIX, 'Preparing TTS request for', tokens)
// First option
if (tokens.length > 1) {
const option1 = tokens[1]
if (model_id.includes("multilingual"))
if (model_id.includes('multilingual'))
language = option1
else
speaker = option1
@ -711,10 +711,10 @@ class CoquiTtsProvider {
'Cache-Control': 'no-cache'
},
body: JSON.stringify({
"text": text,
"model_id": model_id,
"language_id": parseInt(language),
"speaker_id": parseInt(speaker)
'text': text,
'model_id': model_id,
'language_id': parseInt(language),
'speaker_id': parseInt(speaker)
})
});
@ -753,9 +753,9 @@ async function initLocalModels() {
let result = await CoquiTtsProvider.getLocalModelList();
result = await result.json();
coquiLocalModels = result["models_list"];
coquiLocalModels = result['models_list'];
$("#coqui_local_model_name").show();
$('#coqui_local_model_name').show();
$('#coqui_local_model_name')
.find('option')
.remove()
@ -764,7 +764,7 @@ async function initLocalModels() {
.val('none');
for (const model_dataset of coquiLocalModels)
$("#coqui_local_model_name").append(new Option(model_dataset, model_dataset));
$('#coqui_local_model_name').append(new Option(model_dataset, model_dataset));
coquiLocalModelsReceived = true;
}

View File

@ -1,8 +1,8 @@
import { getRequestHeaders } from "../../../script.js"
import { getApiUrl } from "../../extensions.js"
import { doExtrasFetch, modules } from "../../extensions.js"
import { getPreviewString } from "./index.js"
import { saveTtsProviderSettings } from "./index.js"
import { getRequestHeaders } from '../../../script.js'
import { getApiUrl } from '../../extensions.js'
import { doExtrasFetch, modules } from '../../extensions.js'
import { getPreviewString } from './index.js'
import { saveTtsProviderSettings } from './index.js'
export { EdgeTtsProvider }
@ -37,7 +37,7 @@ class EdgeTtsProvider {
async loadSettings(settings) {
// Pupulate Provider UI given input settings
if (Object.keys(settings).length == 0) {
console.info("Using default TTS Provider settings")
console.info('Using default TTS Provider settings')
}
// Only accept keys defined in defaultSettings
@ -53,10 +53,10 @@ class EdgeTtsProvider {
$('#edge_tts_rate').val(this.settings.rate || 0);
$('#edge_tts_rate_output').text(this.settings.rate || 0);
$('#edge_tts_rate').on("input", () => {this.onSettingsChange()})
$('#edge_tts_rate').on('input', () => {this.onSettingsChange()})
await this.checkReady()
console.debug("EdgeTTS: Settings loaded")
console.debug('EdgeTTS: Settings loaded')
}
@ -99,7 +99,7 @@ class EdgeTtsProvider {
throwIfModuleMissing()
const url = new URL(getApiUrl());
url.pathname = `/api/edge-tts/list`
url.pathname = '/api/edge-tts/list'
const response = await doExtrasFetch(url)
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`)
@ -133,15 +133,15 @@ class EdgeTtsProvider {
console.info(`Generating new TTS for voice_id ${voiceId}`)
const url = new URL(getApiUrl());
url.pathname = `/api/edge-tts/generate`;
url.pathname = '/api/edge-tts/generate';
const response = await doExtrasFetch(url,
{
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
"text": inputText,
"voice": voiceId,
"rate": Number(this.settings.rate),
'text': inputText,
'voice': voiceId,
'rate': Number(this.settings.rate),
})
}
)
@ -154,7 +154,7 @@ class EdgeTtsProvider {
}
function throwIfModuleMissing() {
if (!modules.includes('edge-tts')) {
const message = `Edge TTS module not loaded. Add edge-tts to enable-modules and restart the Extras API.`
const message = 'Edge TTS module not loaded. Add edge-tts to enable-modules and restart the Extras API.'
// toastr.error(message)
throw new Error(message)
}

View File

@ -1,4 +1,4 @@
import { saveTtsProviderSettings } from "./index.js"
import { saveTtsProviderSettings } from './index.js'
export { ElevenLabsTtsProvider }
class ElevenLabsTtsProvider {
@ -14,7 +14,7 @@ class ElevenLabsTtsProvider {
defaultSettings = {
stability: 0.75,
similarity_boost: 0.75,
apiKey: "",
apiKey: '',
model: 'eleven_monolingual_v1',
voiceMap: {}
}
@ -53,7 +53,7 @@ class ElevenLabsTtsProvider {
async loadSettings(settings) {
// Pupulate Provider UI given input settings
if (Object.keys(settings).length == 0) {
console.info("Using default TTS Provider settings")
console.info('Using default TTS Provider settings')
}
// Only accept keys defined in defaultSettings
@ -86,9 +86,9 @@ class ElevenLabsTtsProvider {
try {
await this.checkReady()
console.debug("ElevenLabs: Settings loaded")
console.debug('ElevenLabs: Settings loaded')
} catch {
console.debug("ElevenLabs: Settings loaded, but not ready")
console.debug('ElevenLabs: Settings loaded, but not ready')
}
}
@ -113,7 +113,7 @@ class ElevenLabsTtsProvider {
this.settings.apiKey = $('#elevenlabs_tts_api_key').val()
await this.fetchTtsVoiceObjects().catch(error => {
throw `TTS API key validation failed`
throw 'TTS API key validation failed'
})
console.debug(`Saved new API_KEY: ${this.settings.apiKey}`)
$('#tts_status').text('')
@ -146,7 +146,7 @@ class ElevenLabsTtsProvider {
console.debug(`Found existing TTS generation with id ${historyId}`)
response = await this.fetchTtsFromHistory(historyId)
} else {
console.debug(`No existing TTS generation found, requesting new generation`)
console.debug('No existing TTS generation found, requesting new generation')
response = await this.fetchTtsGeneration(text, voiceId)
}
return response
@ -177,7 +177,7 @@ class ElevenLabsTtsProvider {
const headers = {
'xi-api-key': this.settings.apiKey
}
const response = await fetch(`https://api.elevenlabs.io/v1/voices`, {
const response = await fetch('https://api.elevenlabs.io/v1/voices', {
headers: headers
})
if (!response.ok) {
@ -192,7 +192,7 @@ class ElevenLabsTtsProvider {
'xi-api-key': this.settings.apiKey
}
const response = await fetch(
`https://api.elevenlabs.io/v1/voices/settings/default`,
'https://api.elevenlabs.io/v1/voices/settings/default',
{
headers: headers
}
@ -204,7 +204,7 @@ class ElevenLabsTtsProvider {
}
async fetchTtsGeneration(text, voiceId) {
let model = this.settings.model ?? "eleven_monolingual_v1";
let model = this.settings.model ?? 'eleven_monolingual_v1';
console.info(`Generating new TTS for voice_id ${voiceId}, model ${model}`)
const response = await fetch(
`https://api.elevenlabs.io/v1/text-to-speech/${voiceId}`,
@ -251,7 +251,7 @@ class ElevenLabsTtsProvider {
const headers = {
'xi-api-key': this.settings.apiKey
}
const response = await fetch(`https://api.elevenlabs.io/v1/history`, {
const response = await fetch('https://api.elevenlabs.io/v1/history', {
headers: headers
})
if (!response.ok) {

View File

@ -10,7 +10,7 @@ import { NovelTtsProvider } from './novel.js'
import { power_user } from '../../power-user.js'
import { registerSlashCommand } from '../../slash-commands.js'
import { OpenAITtsProvider } from './openai.js'
import {XTTSTtsProvider} from "./xtts.js"
import {XTTSTtsProvider} from './xtts.js'
export { talkingAnimation };
const UPDATE_INTERVAL = 1000
@ -30,13 +30,13 @@ export function getPreviewString(lang) {
'en-GB': 'Sphinx of black quartz, judge my vow',
'fr-FR': 'Portez ce vieux whisky au juge blond qui fume',
'de-DE': 'Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich',
'it-IT': "Pranzo d'acqua fa volti sghembi",
'it-IT': 'Pranzo d\'acqua fa volti sghembi',
'es-ES': 'Quiere la boca exhausta vid, kiwi, piña y fugaz jamón',
'es-MX': 'Fabio me exige, sin tapujos, que añada cerveza al whisky',
'ru-RU': 'В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!',
'pt-BR': 'Vejo xá gritando que fez show sem playback.',
'pt-PR': 'Todo pajé vulgar faz boquinha sexy com kiwi.',
'uk-UA': "Фабрикуймо гідність, лящім їжею, ґав хапаймо, з'єднавці чаш!",
'uk-UA': 'Фабрикуймо гідність, лящім їжею, ґав хапаймо, з\'єднавці чаш!',
'pl-PL': 'Pchnąć w tę łódź jeża lub ośm skrzyń fig',
'cs-CZ': 'Příliš žluťoučký kůň úpěl ďábelské ódy',
'sk-SK': 'Vyhŕňme si rukávy a vyprážajme čínske ryžové cestoviny',
@ -227,16 +227,16 @@ async function moduleWorker() {
function talkingAnimation(switchValue) {
if (!modules.includes('talkinghead')) {
console.debug("Talking Animation module not loaded");
console.debug('Talking Animation module not loaded');
return;
}
const apiUrl = getApiUrl();
const animationType = switchValue ? "start" : "stop";
const animationType = switchValue ? 'start' : 'stop';
if (switchValue !== storedvalue) {
try {
console.log(animationType + " Talking Animation");
console.log(animationType + ' Talking Animation');
doExtrasFetch(`${apiUrl}/api/talkinghead/${animationType}_talking`);
storedvalue = switchValue; // Update the storedvalue to the current switchValue
} catch (error) {
@ -283,16 +283,16 @@ function isTtsProcessing() {
function debugTtsPlayback() {
console.log(JSON.stringify(
{
"ttsProviderName": ttsProviderName,
"voiceMap": voiceMap,
"currentMessageNumber": currentMessageNumber,
"audioPaused": audioPaused,
"audioJobQueue": audioJobQueue,
"currentAudioJob": currentAudioJob,
"audioQueueProcessorReady": audioQueueProcessorReady,
"ttsJobQueue": ttsJobQueue,
"currentTtsJob": currentTtsJob,
"ttsConfig": extension_settings.tts
'ttsProviderName': ttsProviderName,
'voiceMap': voiceMap,
'currentMessageNumber': currentMessageNumber,
'audioPaused': audioPaused,
'audioJobQueue': audioJobQueue,
'currentAudioJob': currentAudioJob,
'audioQueueProcessorReady': audioQueueProcessorReady,
'ttsJobQueue': ttsJobQueue,
'currentTtsJob': currentTtsJob,
'ttsConfig': extension_settings.tts
}
))
}
@ -314,7 +314,7 @@ let audioQueueProcessorReady = true
async function playAudioData(audioBlob) {
// Since current audio job can be cancelled, don't playback if it is null
if (currentAudioJob == null) {
console.log("Cancelled TTS playback because currentAudioJob was null")
console.log('Cancelled TTS playback because currentAudioJob was null')
}
const reader = new FileReader()
reader.onload = function (e) {
@ -324,7 +324,7 @@ async function playAudioData(audioBlob) {
reader.readAsDataURL(audioBlob)
audioElement.addEventListener('ended', completeCurrentAudioJob)
audioElement.addEventListener('canplay', () => {
console.debug(`Starting TTS playback`)
console.debug('Starting TTS playback')
audioElement.play()
})
}
@ -572,7 +572,7 @@ function loadSettings() {
const defaultSettings = {
voiceMap: '',
ttsEnabled: false,
currentProvider: "ElevenLabs",
currentProvider: 'ElevenLabs',
auto_generation: true,
narrate_user: false,
}
@ -645,7 +645,7 @@ function onNarrateTranslatedOnlyClick() {
async function loadTtsProvider(provider) {
//Clear the current config and add new config
$("#tts_provider_settings").html("")
$('#tts_provider_settings').html('')
if (!provider) {
return
@ -858,7 +858,7 @@ export async function initVoiceMap(unrestricted = false) {
return
}
setTtsStatus("TTS Provider Loaded", true)
setTtsStatus('TTS Provider Loaded', true)
// Clear existing voiceMap state
$('#tts_voicemap_block').empty()
@ -869,12 +869,12 @@ export async function initVoiceMap(unrestricted = false) {
// Get saved voicemap from provider settings, handling new and old representations
let voiceMapFromSettings = {}
if ("voiceMap" in extension_settings.tts[ttsProviderName]) {
if ('voiceMap' in extension_settings.tts[ttsProviderName]) {
// Handle previous representation
if (typeof extension_settings.tts[ttsProviderName].voiceMap === "string") {
if (typeof extension_settings.tts[ttsProviderName].voiceMap === 'string') {
voiceMapFromSettings = parseVoiceMap(extension_settings.tts[ttsProviderName].voiceMap)
// Handle new representation
} else if (typeof extension_settings.tts[ttsProviderName].voiceMap === "object") {
} else if (typeof extension_settings.tts[ttsProviderName].voiceMap === 'object') {
voiceMapFromSettings = extension_settings.tts[ttsProviderName].voiceMap
}
}
@ -885,12 +885,12 @@ export async function initVoiceMap(unrestricted = false) {
voiceIdsFromProvider = await ttsProvider.fetchTtsVoiceObjects()
}
catch {
toastr.error("TTS Provider failed to return voice ids.")
toastr.error('TTS Provider failed to return voice ids.')
}
// Build UI using VoiceMapEntry objects
for (const character of characters) {
if (character === "SillyTavern System") {
if (character === 'SillyTavern System') {
continue
}
// Check provider settings for voiceIds
@ -976,7 +976,7 @@ $(document).ready(function () {
$('#tts_narrate_user').on('click', onNarrateUserClick);
$('#tts_voices').on('click', onTtsVoicesClick)
for (const provider in ttsProviders) {
$('#tts_provider').append($("<option />").val(provider).text(provider))
$('#tts_provider').append($('<option />').val(provider).text(provider))
}
$('#tts_provider').on('change', onTtsProviderChange)
$(document).on('click', '.mes_narrate', onNarrateOneMessage);
@ -991,6 +991,6 @@ $(document).ready(function () {
eventSource.on(event_types.CHAT_CHANGED, onChatChanged)
eventSource.on(event_types.MESSAGE_DELETED, onChatDeleted);
eventSource.on(event_types.GROUP_UPDATED, onChatChanged)
registerSlashCommand('speak', onNarrateText, ['narrate', 'tts'], `<span class="monospace">(text)</span> narrate any text using currently selected character's voice. Use voice="Character Name" argument to set other voice from the voice map, example: <tt>/speak voice="Donald Duck" Quack!</tt>`, true, true);
registerSlashCommand('speak', onNarrateText, ['narrate', 'tts'], '<span class="monospace">(text)</span> narrate any text using currently selected character\'s voice. Use voice="Character Name" argument to set other voice from the voice map, example: <tt>/speak voice="Donald Duck" Quack!</tt>', true, true);
document.body.appendChild(audioElement);
})

View File

@ -1,6 +1,6 @@
import { getRequestHeaders, callPopup } from "../../../script.js"
import { getPreviewString, saveTtsProviderSettings } from "./index.js"
import { initVoiceMap } from "./index.js"
import { getRequestHeaders, callPopup } from '../../../script.js'
import { getPreviewString, saveTtsProviderSettings } from './index.js'
import { initVoiceMap } from './index.js'
export { NovelTtsProvider }
@ -62,7 +62,7 @@ class NovelTtsProvider {
// Delete selected custom voice from provider
deleteCustomVoice() {
const selected = $("#tts-novel-custom-voices-select").find(':selected').val();
const selected = $('#tts-novel-custom-voices-select').find(':selected').val();
const voiceIndex = this.settings.customVoices.indexOf(selected);
if (voiceIndex !== -1) {
@ -75,7 +75,7 @@ class NovelTtsProvider {
// Create the UI dropdown list of voices in provider
populateCustomVoices(){
let voiceSelect = $("#tts-novel-custom-voices-select")
let voiceSelect = $('#tts-novel-custom-voices-select')
voiceSelect.empty()
this.settings.customVoices.forEach(voice => {
voiceSelect.append(`<option>${voice}</option>`)
@ -85,10 +85,10 @@ class NovelTtsProvider {
async loadSettings(settings) {
// Populate Provider UI given input settings
if (Object.keys(settings).length == 0) {
console.info("Using default TTS Provider settings")
console.info('Using default TTS Provider settings')
}
$("#tts-novel-custom-voices-add").on('click', () => (this.addCustomVoice()))
$("#tts-novel-custom-voices-delete").on('click',() => (this.deleteCustomVoice()))
$('#tts-novel-custom-voices-add').on('click', () => (this.addCustomVoice()))
$('#tts-novel-custom-voices-delete').on('click',() => (this.deleteCustomVoice()))
// Only accept keys defined in defaultSettings
this.settings = this.defaultSettings
@ -103,7 +103,7 @@ class NovelTtsProvider {
this.populateCustomVoices()
await this.checkReady()
console.debug("NovelTTS: Settings loaded")
console.debug('NovelTTS: Settings loaded')
}
// Perform a simple readiness check by trying to fetch voiceIds
@ -122,7 +122,7 @@ class NovelTtsProvider {
async getVoice(voiceName) {
if (!voiceName) {
throw `TTS Voice name not provided`
throw 'TTS Voice name not provided'
}
return { name: voiceName, voice_id: voiceName, lang: 'en-US', preview_url: false}
@ -181,13 +181,13 @@ class NovelTtsProvider {
async fetchTtsGeneration(inputText, voiceId) {
console.info(`Generating new TTS for voice_id ${voiceId}`)
const response = await fetch(`/api/novelai/generate-voice`,
const response = await fetch('/api/novelai/generate-voice',
{
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
"text": inputText,
"voice": voiceId,
'text': inputText,
'voice': voiceId,
})
}
)

View File

@ -1,5 +1,5 @@
import { getRequestHeaders } from "../../../script.js"
import { saveTtsProviderSettings } from "./index.js";
import { getRequestHeaders } from '../../../script.js'
import { saveTtsProviderSettings } from './index.js';
export { OpenAITtsProvider }
@ -52,7 +52,7 @@ class OpenAITtsProvider {
async loadSettings(settings) {
// Populate Provider UI given input settings
if (Object.keys(settings).length == 0) {
console.info("Using default TTS Provider settings")
console.info('Using default TTS Provider settings')
}
// Only accept keys defined in defaultSettings
@ -79,7 +79,7 @@ class OpenAITtsProvider {
$('#openai-tts-speed-output').text(this.settings.speed);
await this.checkReady();
console.debug("OpenAI TTS: Settings loaded");
console.debug('OpenAI TTS: Settings loaded');
}
onSettingsChange() {
@ -100,7 +100,7 @@ class OpenAITtsProvider {
async getVoice(voiceName) {
if (!voiceName) {
throw `TTS Voice name not provided`
throw 'TTS Voice name not provided'
}
const voice = OpenAITtsProvider.voices.find(voice => voice.voice_id === voiceName || voice.name === voiceName);
@ -127,14 +127,14 @@ class OpenAITtsProvider {
async fetchTtsGeneration(inputText, voiceId) {
console.info(`Generating new TTS for voice_id ${voiceId}`)
const response = await fetch(`/api/openai/generate-voice`, {
const response = await fetch('/api/openai/generate-voice', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
"text": inputText,
"voice": voiceId,
"model": this.settings.model,
"speed": this.settings.speed,
'text': inputText,
'voice': voiceId,
'model': this.settings.model,
'speed': this.settings.speed,
}),
});

View File

@ -1,5 +1,5 @@
import { doExtrasFetch, getApiUrl, modules } from "../../extensions.js"
import { saveTtsProviderSettings } from "./index.js"
import { doExtrasFetch, getApiUrl, modules } from '../../extensions.js'
import { saveTtsProviderSettings } from './index.js'
export { SileroTtsProvider }
@ -14,7 +14,7 @@ class SileroTtsProvider {
separator = ' .. '
defaultSettings = {
provider_endpoint: "http://localhost:8001/tts",
provider_endpoint: 'http://localhost:8001/tts',
voiceMap: {}
}
@ -38,7 +38,7 @@ class SileroTtsProvider {
async loadSettings(settings) {
// Pupulate Provider UI given input settings
if (Object.keys(settings).length == 0) {
console.info("Using default TTS Provider settings")
console.info('Using default TTS Provider settings')
}
// Only accept keys defined in defaultSettings
@ -64,12 +64,12 @@ class SileroTtsProvider {
}, 2000);
$('#silero_tts_endpoint').val(this.settings.provider_endpoint)
$('#silero_tts_endpoint').on("input", () => { this.onSettingsChange() })
$('#silero_tts_endpoint').on('input', () => { this.onSettingsChange() })
this.refreshSession()
await this.checkReady()
console.debug("SileroTTS: Settings loaded")
console.debug('SileroTTS: Settings loaded')
}
// Perform a simple readiness check by trying to fetch voiceIds
@ -130,9 +130,9 @@ class SileroTtsProvider {
'Cache-Control': 'no-cache' // Added this line to disable caching of file so new files are always played - Rolyat 7/7/23
},
body: JSON.stringify({
"text": inputText,
"speaker": voiceId,
"session": "sillytavern"
'text': inputText,
'speaker': voiceId,
'session': 'sillytavern'
})
}
)
@ -144,7 +144,7 @@ class SileroTtsProvider {
}
async initSession() {
console.info(`Silero TTS: requesting new session`);
console.info('Silero TTS: requesting new session');
try {
const response = await doExtrasFetch(
`${this.settings.provider_endpoint}/session`,
@ -155,7 +155,7 @@ class SileroTtsProvider {
'Cache-Control': 'no-cache',
},
body: JSON.stringify({
"path": "sillytavern",
'path': 'sillytavern',
}),
}
)

View File

@ -1,7 +1,7 @@
import { isMobile } from "../../RossAscends-mods.js";
import { getPreviewString } from "./index.js";
import { isMobile } from '../../RossAscends-mods.js';
import { getPreviewString } from './index.js';
import { talkingAnimation } from './index.js';
import { saveTtsProviderSettings } from "./index.js"
import { saveTtsProviderSettings } from './index.js'
export { SystemTtsProvider }
/**
@ -92,7 +92,7 @@ class SystemTtsProvider {
get settingsHtml() {
if (!('speechSynthesis' in window)) {
return "Your browser or operating system doesn't support speech synthesis";
return 'Your browser or operating system doesn\'t support speech synthesis';
}
return `<p>Uses the voices provided by your operating system</p>
@ -113,7 +113,7 @@ class SystemTtsProvider {
async loadSettings(settings) {
// Populate Provider UI given input settings
if (Object.keys(settings).length == 0) {
console.info("Using default TTS Provider settings");
console.info('Using default TTS Provider settings');
}
// iOS should only allows speech synthesis trigged by user interaction
@ -146,12 +146,12 @@ class SystemTtsProvider {
$('#system_tts_pitch').val(this.settings.pitch || this.defaultSettings.pitch);
// Trigger updates
$('#system_tts_rate').on("input", () => { this.onSettingsChange() })
$('#system_tts_rate').on("input", () => { this.onSettingsChange() })
$('#system_tts_rate').on('input', () => { this.onSettingsChange() })
$('#system_tts_rate').on('input', () => { this.onSettingsChange() })
$('#system_tts_pitch_output').text(this.settings.pitch);
$('#system_tts_rate_output').text(this.settings.rate);
console.debug("SystemTTS: Settings loaded");
console.debug('SystemTTS: Settings loaded');
}
// Perform a simple readiness check by trying to fetch voiceIds

View File

@ -1,5 +1,5 @@
import { doExtrasFetch, getApiUrl, modules } from "../../extensions.js"
import { saveTtsProviderSettings } from "./index.js"
import { doExtrasFetch, getApiUrl, modules } from '../../extensions.js'
import { saveTtsProviderSettings } from './index.js'
export { XTTSTtsProvider }
@ -29,28 +29,28 @@ class XTTSTtsProvider {
}
languageLabels = {
"Arabic": "ar",
"Brazilian Portuguese": "pt",
"Chinese": "zh-cn",
"Czech": "cs",
"Dutch": "nl",
"English": "en",
"French": "fr",
"German": "de",
"Italian": "it",
"Polish": "pl",
"Russian": "ru",
"Spanish": "es",
"Turkish": "tr",
"Japanese": "ja",
"Korean": "ko",
"Hungarian": "hu",
"Hindi": "hi",
'Arabic': 'ar',
'Brazilian Portuguese': 'pt',
'Chinese': 'zh-cn',
'Czech': 'cs',
'Dutch': 'nl',
'English': 'en',
'French': 'fr',
'German': 'de',
'Italian': 'it',
'Polish': 'pl',
'Russian': 'ru',
'Spanish': 'es',
'Turkish': 'tr',
'Japanese': 'ja',
'Korean': 'ko',
'Hungarian': 'hu',
'Hindi': 'hi',
}
defaultSettings = {
provider_endpoint: "http://localhost:8020",
language: "en",
provider_endpoint: 'http://localhost:8020',
language: 'en',
voiceMap: {}
}
@ -96,7 +96,7 @@ class XTTSTtsProvider {
async loadSettings(settings) {
// Pupulate Provider UI given input settings
if (Object.keys(settings).length == 0) {
console.info("Using default TTS Provider settings")
console.info('Using default TTS Provider settings')
}
// Only accept keys defined in defaultSettings
@ -122,13 +122,13 @@ class XTTSTtsProvider {
}, 2000);
$('#xtts_tts_endpoint').val(this.settings.provider_endpoint)
$('#xtts_tts_endpoint').on("input", () => { this.onSettingsChange() })
$('#xtts_tts_endpoint').on('input', () => { this.onSettingsChange() })
$('#xtts_api_language').val(this.settings.language)
$('#xtts_api_language').on("change", () => { this.onSettingsChange() })
$('#xtts_api_language').on('change', () => { this.onSettingsChange() })
await this.checkReady()
console.debug("XTTS: Settings loaded")
console.debug('XTTS: Settings loaded')
}
// Perform a simple readiness check by trying to fetch voiceIds
@ -185,9 +185,9 @@ class XTTSTtsProvider {
'Cache-Control': 'no-cache' // Added this line to disable caching of file so new files are always played - Rolyat 7/7/23
},
body: JSON.stringify({
"text": inputText,
"speaker_wav": voiceId,
"language": this.settings.language
'text': inputText,
'speaker_wav': voiceId,
'language': this.settings.language
})
}
)

View File

@ -1,8 +1,8 @@
import { eventSource, event_types, extension_prompt_types, getCurrentChatId, getRequestHeaders, is_send_press, saveSettingsDebounced, setExtensionPrompt, substituteParams } from "../../../script.js";
import { ModuleWorkerWrapper, extension_settings, getContext, renderExtensionTemplate } from "../../extensions.js";
import { collapseNewlines, power_user, ui_mode } from "../../power-user.js";
import { SECRET_KEYS, secret_state } from "../../secrets.js";
import { debounce, getStringHash as calculateHash, waitUntilCondition, onlyUnique, splitRecursive } from "../../utils.js";
import { eventSource, event_types, extension_prompt_types, getCurrentChatId, getRequestHeaders, is_send_press, saveSettingsDebounced, setExtensionPrompt, substituteParams } from '../../../script.js';
import { ModuleWorkerWrapper, extension_settings, getContext, renderExtensionTemplate } from '../../extensions.js';
import { collapseNewlines, power_user, ui_mode } from '../../power-user.js';
import { SECRET_KEYS, secret_state } from '../../secrets.js';
import { debounce, getStringHash as calculateHash, waitUntilCondition, onlyUnique, splitRecursive } from '../../utils.js';
const MODULE_NAME = 'vectors';
@ -14,7 +14,7 @@ const settings = {
// For chats
enabled_chats: false,
template: `Past events: {{text}}`,
template: 'Past events: {{text}}',
depth: 2,
position: extension_prompt_types.IN_PROMPT,
protect: 5,
@ -234,7 +234,7 @@ async function retrieveFileChunks(queryText, collectionId) {
*/
async function vectorizeFile(fileText, fileName, collectionId) {
try {
toastr.info("Vectorization may take some time, please wait...", `Ingesting file ${fileName}`);
toastr.info('Vectorization may take some time, please wait...', `Ingesting file ${fileName}`);
const chunks = splitRecursive(fileText, settings.chunk_size);
console.debug(`Vectors: Split file ${fileName} into ${chunks.length} chunks`, chunks);