diff --git a/public/scripts/extensions/translate/index.js b/public/scripts/extensions/translate/index.js index 488ab2071..3eb7ad055 100644 --- a/public/scripts/extensions/translate/index.js +++ b/public/scripts/extensions/translate/index.js @@ -185,7 +185,7 @@ async function translateIncomingMessage(messageId) { } async function translateProviderLibre(text, lang) { - const response = await fetch('/libre_translate', { + const response = await fetch('/api/translate/libre', { method: 'POST', headers: getRequestHeaders(), body: JSON.stringify({ text: text, lang: lang }), @@ -200,7 +200,7 @@ async function translateProviderLibre(text, lang) { } async function translateProviderGoogle(text, lang) { - const response = await fetch('/google_translate', { + const response = await fetch('/api/translate/google', { method: 'POST', headers: getRequestHeaders(), body: JSON.stringify({ text: text, lang: lang }), @@ -219,7 +219,7 @@ async function translateProviderDeepl(text, lang) { throw new Error('No DeepL API key'); } - const response = await fetch('/deepl_translate', { + const response = await fetch('/api/translate/deepl', { method: 'POST', headers: getRequestHeaders(), body: JSON.stringify({ text: text, lang: lang }), diff --git a/server.js b/server.js index c566422b3..a2bbd5ccb 100644 --- a/server.js +++ b/server.js @@ -56,7 +56,6 @@ const { Tokenizer } = require('@agnai/web-tokenizers'); // misc/other imports const _ = require('lodash'); -const { generateRequestUrl, normaliseResponse } = require('google-translate-api-browser'); // Unrestrict console logs display limit util.inspect.defaultOptions.maxArrayLength = null; @@ -4754,127 +4753,6 @@ app.post('/api/sd/generate', jsonParser, async (request, response) => { } }); -app.post('/libre_translate', jsonParser, async (request, response) => { - const key = readSecret(SECRET_KEYS.LIBRE); - const url = readSecret(SECRET_KEYS.LIBRE_URL); - - if (!url) { - console.log('LibreTranslate URL is not configured.'); - return response.sendStatus(401); - } - - const text = request.body.text; - const lang = request.body.lang; - - if (!text || !lang) { - return response.sendStatus(400); - } - - console.log('Input text: ' + text); - - try { - const result = await fetch(url, { - method: "POST", - body: JSON.stringify({ - q: text, - source: "auto", - target: lang, - format: "text", - api_key: key - }), - headers: { "Content-Type": "application/json" } - }); - - if (!result.ok) { - return response.sendStatus(result.status); - } - - const json = await result.json(); - console.log('Translated text: ' + json.translatedText); - - return response.send(json.translatedText); - } catch (error) { - console.log("Translation error: " + error.message); - return response.sendStatus(500); - } -}); - -app.post('/google_translate', jsonParser, async (request, response) => { - const text = request.body.text; - const lang = request.body.lang; - - if (!text || !lang) { - return response.sendStatus(400); - } - - console.log('Input text: ' + text); - - const url = generateRequestUrl(text, { to: lang }); - - https.get(url, (resp) => { - let data = ''; - - resp.on('data', (chunk) => { - data += chunk; - }); - - resp.on('end', () => { - const result = normaliseResponse(JSON.parse(data)); - console.log('Translated text: ' + result.text); - return response.send(result.text); - }); - }).on("error", (err) => { - console.log("Translation error: " + err.message); - return response.sendStatus(500); - }); -}); - -app.post('/deepl_translate', jsonParser, async (request, response) => { - const key = readSecret(SECRET_KEYS.DEEPL); - - if (!key) { - return response.sendStatus(401); - } - - const text = request.body.text; - const lang = request.body.lang; - - if (!text || !lang) { - return response.sendStatus(400); - } - - console.log('Input text: ' + text); - - const params = new URLSearchParams(); - params.append('text', text); - params.append('target_lang', lang); - - try { - const result = await fetch('https://api-free.deepl.com/v2/translate', { - method: 'POST', - body: params, - headers: { - 'Accept': 'application/json', - 'Authorization': `DeepL-Auth-Key ${key}`, - 'Content-Type': 'application/x-www-form-urlencoded', - }, - timeout: 0, - }); - - if (!result.ok) { - return response.sendStatus(result.status); - } - - const json = await result.json(); - console.log('Translated text: ' + json.translations[0].text); - - return response.send(json.translations[0].text); - } catch (error) { - console.log("Translation error: " + error.message); - return response.sendStatus(500); - } -}); - app.post('/novel_tts', jsonParser, async (request, response) => { const token = readSecret(SECRET_KEYS.NOVEL); @@ -5771,6 +5649,8 @@ app.post('/get_character_assets_list', jsonParser, async (request, response) => // Vector storage DB require('./src/vectors').registerEndpoints(app, jsonParser); +// Chat translation +require('./src/translate').registerEndpoints(app, jsonParser); // Emotion classification import('./src/classify.mjs').then(module => { module.default.registerEndpoints(app, jsonParser); diff --git a/src/translate.js b/src/translate.js new file mode 100644 index 000000000..9e11bd433 --- /dev/null +++ b/src/translate.js @@ -0,0 +1,139 @@ +const fetch = require('node-fetch').default; +const https = require('https'); +const { readSecret, SECRET_KEYS } = require('./secrets'); +const { generateRequestUrl, normaliseResponse } = require('google-translate-api-browser'); + +/** + * @param {import("express").Express} app + * @param {any} jsonParser + */ +function registerEndpoints(app, jsonParser) { + app.post('/api/translate/libre', jsonParser, async (request, response) => { + const key = readSecret(SECRET_KEYS.LIBRE); + const url = readSecret(SECRET_KEYS.LIBRE_URL); + + if (!url) { + console.log('LibreTranslate URL is not configured.'); + return response.sendStatus(401); + } + + const text = request.body.text; + const lang = request.body.lang; + + if (!text || !lang) { + return response.sendStatus(400); + } + + console.log('Input text: ' + text); + + try { + const result = await fetch(url, { + method: "POST", + body: JSON.stringify({ + q: text, + source: "auto", + target: lang, + format: "text", + api_key: key + }), + headers: { "Content-Type": "application/json" } + }); + + if (!result.ok) { + const error = await result.text(); + console.log('LibreTranslate error: ', result.statusText, error); + return response.sendStatus(result.status); + } + + const json = await result.json(); + console.log('Translated text: ' + json.translatedText); + + return response.send(json.translatedText); + } catch (error) { + console.log("Translation error: " + error.message); + return response.sendStatus(500); + } + }); + + app.post('/api/translate/google', jsonParser, async (request, response) => { + const text = request.body.text; + const lang = request.body.lang; + + if (!text || !lang) { + return response.sendStatus(400); + } + + console.log('Input text: ' + text); + + const url = generateRequestUrl(text, { to: lang }); + + https.get(url, (resp) => { + let data = ''; + + resp.on('data', (chunk) => { + data += chunk; + }); + + resp.on('end', () => { + const result = normaliseResponse(JSON.parse(data)); + console.log('Translated text: ' + result.text); + return response.send(result.text); + }); + }).on("error", (err) => { + console.log("Translation error: " + err.message); + return response.sendStatus(500); + }); + }); + + app.post('/api/translate/deepl', jsonParser, async (request, response) => { + const key = readSecret(SECRET_KEYS.DEEPL); + + if (!key) { + return response.sendStatus(401); + } + + const text = request.body.text; + const lang = request.body.lang; + + if (!text || !lang) { + return response.sendStatus(400); + } + + console.log('Input text: ' + text); + + const params = new URLSearchParams(); + params.append('text', text); + params.append('target_lang', lang); + + try { + const result = await fetch('https://api-free.deepl.com/v2/translate', { + method: 'POST', + body: params, + headers: { + 'Accept': 'application/json', + 'Authorization': `DeepL-Auth-Key ${key}`, + 'Content-Type': 'application/x-www-form-urlencoded', + }, + timeout: 0, + }); + + if (!result.ok) { + const error = await result.text(); + console.log('DeepL error: ', result.statusText, error); + return response.sendStatus(result.status); + } + + const json = await result.json(); + console.log('Translated text: ' + json.translations[0].text); + + return response.send(json.translations[0].text); + } catch (error) { + console.log("Translation error: " + error.message); + return response.sendStatus(500); + } + }); +} + +module.exports = { + registerEndpoints, +};