diff --git a/public/scripts/extensions/stable-diffusion/index.js b/public/scripts/extensions/stable-diffusion/index.js index efb190770..f641a0c94 100644 --- a/public/scripts/extensions/stable-diffusion/index.js +++ b/public/scripts/extensions/stable-diffusion/index.js @@ -162,8 +162,11 @@ const defaultSettings = { // AUTOMATIC1111 settings auto_url: 'http://localhost:7860', + auto_auth: '', } +const getAutoRequestBody = () => ({ url: extension_settings.sd.auto_url, auth: extension_settings.sd.auto_auth }); + function toggleSourceControls() { $('.sd_settings [data-sd-source]').each(function () { const source = $(this).data('sd-source'); @@ -213,6 +216,7 @@ async function loadSettings() { $('#sd_enable_hr').prop('checked', extension_settings.sd.enable_hr); $('#sd_refine_mode').prop('checked', extension_settings.sd.refine_mode); $('#sd_auto_url').val(extension_settings.sd.auto_url); + $('#sd_auto_auth').val(extension_settings.sd.auto_auth); toggleSourceControls(); addPromptTemplates(); @@ -393,6 +397,11 @@ function onAutoUrlInput() { saveSettingsDebounced(); } +function onAutoAuthInput() { + extension_settings.sd.auto_auth = $('#sd_auto_auth').val(); + saveSettingsDebounced(); +} + async function validateAutoUrl() { try { if (!extension_settings.sd.auto_url) { @@ -402,7 +411,7 @@ async function validateAutoUrl() { const result = await fetch('/api/sd/ping', { method: 'POST', headers: getRequestHeaders(), - body: JSON.stringify({ url: extension_settings.sd.auto_url }), + body: JSON.stringify(getAutoRequestBody()), }); if (!result.ok) { @@ -442,7 +451,7 @@ async function getAutoRemoteModel() { const result = await fetch('/api/sd/get-model', { method: 'POST', headers: getRequestHeaders(), - body: JSON.stringify({ url: extension_settings.sd.auto_url }), + body: JSON.stringify(getAutoRequestBody()), }); if (!result.ok) { @@ -462,7 +471,7 @@ async function updateAutoRemoteModel() { const result = await fetch('/api/sd/set-model', { method: 'POST', headers: getRequestHeaders(), - body: JSON.stringify({ url: extension_settings.sd.auto_url, model: extension_settings.sd.model }), + body: JSON.stringify({ ...getAutoRequestBody(), model: extension_settings.sd.model }), }); if (!result.ok) { @@ -557,7 +566,7 @@ async function loadAutoSamplers() { const result = await fetch('/api/sd/samplers', { method: 'POST', headers: getRequestHeaders(), - body: JSON.stringify({ url: extension_settings.sd.auto_url }), + body: JSON.stringify(getAutoRequestBody()), }); if (!result.ok) { @@ -674,7 +683,7 @@ async function loadAutoModels() { const result = await fetch('/api/sd/models', { method: 'POST', headers: getRequestHeaders(), - body: JSON.stringify({ url: extension_settings.sd.auto_url }), + body: JSON.stringify(getAutoRequestBody()), }); if (!result.ok) { @@ -1000,7 +1009,7 @@ async function generateAutoImage(prompt) { method: 'POST', headers: getRequestHeaders(), body: JSON.stringify({ - url: extension_settings.sd.auto_url, + ...getAutoRequestBody(), prompt: prompt, negative_prompt: extension_settings.sd.negative_prompt, sampler_name: extension_settings.sd.sampler, @@ -1262,6 +1271,7 @@ jQuery(async () => { $('#sd_character_prompt').on('input', onCharacterPromptInput); $('#sd_auto_validate').on('click', validateAutoUrl); $('#sd_auto_url').on('input', onAutoUrlInput); + $('#sd_auto_auth').on('input', onAutoAuthInput); $('#sd_character_prompt_block').hide(); $('.sd_settings .inline-drawer-toggle').on('click', function () { diff --git a/public/scripts/extensions/stable-diffusion/settings.html b/public/scripts/extensions/stable-diffusion/settings.html index 110467d37..873fea5d3 100644 --- a/public/scripts/extensions/stable-diffusion/settings.html +++ b/public/scripts/extensions/stable-diffusion/settings.html @@ -22,7 +22,7 @@
- +
+ + Important: run SD Web UI with the --api flag! The server must be accessible from the SillyTavern host machine.
diff --git a/server.js b/server.js index 509d2adb4..45e596bfa 100644 --- a/server.js +++ b/server.js @@ -193,6 +193,16 @@ function getOverrideHeaders(urlHost) { } } +/** + * Encodes the Basic Auth header value for the given user and password. + * @param {string} auth username:password + * @returns {string} Basic Auth header value + */ +function getBasicAuthHeader(auth) { + const encoded = Buffer.from(`${auth}`).toString('base64'); + return `Basic ${encoded}`; +} + //RossAscends: Added function to format dates used in files and chat timestamps to a humanized format. //Mostly I wanted this to be for file names, but couldn't figure out exactly where the filename save code was as everything seemed to be connected. //During testing, this performs the same as previous date.now() structure. @@ -4532,7 +4542,12 @@ app.post('/api/sd/ping', jsonParser, async (request, response) => { const url = new URL(request.body.url); url.pathname = '/internal/ping'; - const result = await fetch(url); + const result = await fetch(url, { + method: 'GET', + headers: { + 'Authorization': getBasicAuthHeader(request.body.auth), + } + }); if (!result.ok) { throw new Error('SD WebUI returned an error.'); @@ -4550,7 +4565,12 @@ app.post('/api/sd/samplers', jsonParser, async (request, response) => { const url = new URL(request.body.url); url.pathname = '/sdapi/v1/samplers'; - const result = await fetch(url); + const result = await fetch(url, { + method: 'GET', + headers: { + 'Authorization': getBasicAuthHeader(request.body.auth), + }, + }); if (!result.ok) { throw new Error('SD WebUI returned an error.'); @@ -4571,7 +4591,12 @@ app.post('/api/sd/models', jsonParser, async (request, response) => { const url = new URL(request.body.url); url.pathname = '/sdapi/v1/sd-models'; - const result = await fetch(url); + const result = await fetch(url, { + method: 'GET', + headers: { + 'Authorization': getBasicAuthHeader(request.body.auth), + }, + }); if (!result.ok) { throw new Error('SD WebUI returned an error.'); @@ -4591,7 +4616,12 @@ app.post('/api/sd/get-model', jsonParser, async (request, response) => { const url = new URL(request.body.url); url.pathname = '/sdapi/v1/options'; - const result = await fetch(url); + const result = await fetch(url, { + method: 'GET', + headers: { + 'Authorization': getBasicAuthHeader(request.body.auth), + }, + }); const data = await result.json(); return response.send(data['sd_model_checkpoint']); } catch (error) { @@ -4606,7 +4636,12 @@ app.post('/api/sd/set-model', jsonParser, async (request, response) => { const url = new URL(request.body.url); url.pathname = '/sdapi/v1/progress'; - const result = await fetch(url); + const result = await fetch(url, { + method: 'GET', + headers: { + 'Authorization': getBasicAuthHeader(request.body.auth), + }, + }); const data = await result.json(); return data; } @@ -4621,7 +4656,10 @@ app.post('/api/sd/set-model', jsonParser, async (request, response) => { const result = await fetch(url, { method: 'POST', body: JSON.stringify(options), - headers: { 'Content-Type': 'application/json' }, + headers: { + 'Content-Type': 'application/json', + 'Authorization': getBasicAuthHeader(request.body.auth), + }, }); if (!result.ok) { @@ -4659,7 +4697,10 @@ app.post('/api/sd/generate', jsonParser, async (request, response) => { const result = await fetch(url, { method: 'POST', body: JSON.stringify(request.body), - headers: { 'Content-Type': 'application/json' }, + headers: { + 'Content-Type': 'application/json', + 'Authorization': getBasicAuthHeader(request.body.auth), + }, }); if (!result.ok) {