mirror of
				https://github.com/SillyTavern/SillyTavern.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	(beta) Message translate plugin
This commit is contained in:
		
							
								
								
									
										6
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -19,6 +19,7 @@ | |||||||
|                 "device-detector-js": "^3.0.3", |                 "device-detector-js": "^3.0.3", | ||||||
|                 "exifreader": "^4.12.0", |                 "exifreader": "^4.12.0", | ||||||
|                 "express": "^4.18.2", |                 "express": "^4.18.2", | ||||||
|  |                 "google-translate-api-browser": "^3.0.1", | ||||||
|                 "gpt3-tokenizer": "^1.1.5", |                 "gpt3-tokenizer": "^1.1.5", | ||||||
|                 "ip-matching": "^2.1.2", |                 "ip-matching": "^2.1.2", | ||||||
|                 "ipaddr.js": "^2.0.1", |                 "ipaddr.js": "^2.0.1", | ||||||
| @@ -1525,6 +1526,11 @@ | |||||||
|                 "url": "https://github.com/sponsors/sindresorhus" |                 "url": "https://github.com/sponsors/sindresorhus" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|  |         "node_modules/google-translate-api-browser": { | ||||||
|  |             "version": "3.0.1", | ||||||
|  |             "resolved": "https://registry.npmjs.org/google-translate-api-browser/-/google-translate-api-browser-3.0.1.tgz", | ||||||
|  |             "integrity": "sha512-KTLodkyGBWMK9IW6QIeJ2zCuju4Z0CLpbkADKo+yLhbSTD4l+CXXpQ/xaynGVAzeBezzJG6qn8MLeqOq3SmW0A==" | ||||||
|  |         }, | ||||||
|         "node_modules/gpt3-tokenizer": { |         "node_modules/gpt3-tokenizer": { | ||||||
|             "version": "1.1.5", |             "version": "1.1.5", | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ | |||||||
|         "device-detector-js": "^3.0.3", |         "device-detector-js": "^3.0.3", | ||||||
|         "exifreader": "^4.12.0", |         "exifreader": "^4.12.0", | ||||||
|         "express": "^4.18.2", |         "express": "^4.18.2", | ||||||
|  |         "google-translate-api-browser": "^3.0.1", | ||||||
|         "gpt3-tokenizer": "^1.1.5", |         "gpt3-tokenizer": "^1.1.5", | ||||||
|         "ip-matching": "^2.1.2", |         "ip-matching": "^2.1.2", | ||||||
|         "ipaddr.js": "^2.0.1", |         "ipaddr.js": "^2.0.1", | ||||||
|   | |||||||
| @@ -2528,6 +2528,7 @@ | |||||||
|                     <span class="name_text">${characterName}</span> |                     <span class="name_text">${characterName}</span> | ||||||
|  |  | ||||||
|                     <div class="mes_buttons"> |                     <div class="mes_buttons"> | ||||||
|  |                         <div title="Translate message" class="mes_translate fa-solid fa-language"></div> | ||||||
|                         <div title="Open bookmark chat" class="mes_bookmark fa-solid fa-bookmark"></div> |                         <div title="Open bookmark chat" class="mes_bookmark fa-solid fa-bookmark"></div> | ||||||
|                         <div title="Generate Image" class="sd_message_gen fa-solid fa-paintbrush"></div> |                         <div title="Generate Image" class="sd_message_gen fa-solid fa-paintbrush"></div> | ||||||
|                         <div title="Narrate" class="mes_narrate fa-solid fa-bullhorn"></div> |                         <div title="Narrate" class="mes_narrate fa-solid fa-bullhorn"></div> | ||||||
|   | |||||||
| @@ -1135,6 +1135,10 @@ function addCopyToCodeBlocks(messageElement) { | |||||||
| function addOneMessage(mes, { type = "normal", insertAfter = null, scroll = true } = {}) { | function addOneMessage(mes, { type = "normal", insertAfter = null, scroll = true } = {}) { | ||||||
|     var messageText = mes["mes"]; |     var messageText = mes["mes"]; | ||||||
|  |  | ||||||
|  |     if (mes?.extra?.display_text) { | ||||||
|  |         messageText = mes.extra.display_text; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (mes.name === name1) { |     if (mes.name === name1) { | ||||||
|         var characterName = name1; //set to user's name by default |         var characterName = name1; //set to user's name by default | ||||||
|     } else { var characterName = mes.name } |     } else { var characterName = mes.name } | ||||||
| @@ -4803,6 +4807,16 @@ function swipe_left() {      // when we swipe left..but no generation. | |||||||
|         this_mes_div.css('height', this_mes_div_height); |         this_mes_div.css('height', this_mes_div_height); | ||||||
|         const this_mes_block_height = this_mes_block[0].scrollHeight; |         const this_mes_block_height = this_mes_block[0].scrollHeight; | ||||||
|         chat[chat.length - 1]['mes'] = chat[chat.length - 1]['swipes'][chat[chat.length - 1]['swipe_id']]; |         chat[chat.length - 1]['mes'] = chat[chat.length - 1]['swipes'][chat[chat.length - 1]['swipe_id']]; | ||||||
|  |         if (chat[chat.length - 1].extra) { | ||||||
|  |             // if message has memory attached - remove it to allow regen | ||||||
|  |             if (chat[chat.length - 1].extra.memory) { | ||||||
|  |                 delete chat[chat.length - 1].extra.memory; | ||||||
|  |             } | ||||||
|  |             // ditto for display text | ||||||
|  |             if (chat[chat.length - 1].extra.display_text) { | ||||||
|  |                 delete chat[chat.length - 1].extra.display_text; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         $(this).parent().children('.mes_block').transition({ |         $(this).parent().children('.mes_block').transition({ | ||||||
|             x: swipe_range, |             x: swipe_range, | ||||||
|             duration: swipe_duration, |             duration: swipe_duration, | ||||||
| @@ -4901,9 +4915,15 @@ const swipe_right = () => { | |||||||
|         chat[chat.length - 1]['swipes'][0] = chat[chat.length - 1]['mes'];  //assign swipe array with last message from chat |         chat[chat.length - 1]['swipes'][0] = chat[chat.length - 1]['mes'];  //assign swipe array with last message from chat | ||||||
|     } |     } | ||||||
|     chat[chat.length - 1]['swipe_id']++;                                      //make new slot in array |     chat[chat.length - 1]['swipe_id']++;                                      //make new slot in array | ||||||
|     // if message has memory attached - remove it to allow regen |     if (chat[chat.length - 1].extra) { | ||||||
|     if (chat[chat.length - 1].extra && chat[chat.length - 1].extra.memory) { |         // if message has memory attached - remove it to allow regen | ||||||
|         delete chat[chat.length - 1].extra.memory; |         if ( chat[chat.length - 1].extra.memory) { | ||||||
|  |             delete chat[chat.length - 1].extra.memory; | ||||||
|  |         } | ||||||
|  |         // ditto for display text | ||||||
|  |         if (chat[chat.length - 1].extra.display_text) { | ||||||
|  |             delete chat[chat.length - 1].extra.display_text; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     //console.log(chat[chat.length-1]['swipes']); |     //console.log(chat[chat.length-1]['swipes']); | ||||||
|     if (parseInt(chat[chat.length - 1]['swipe_id']) === chat[chat.length - 1]['swipes'].length) { //if swipe id of last message is the same as the length of the 'swipes' array |     if (parseInt(chat[chat.length - 1]['swipe_id']) === chat[chat.length - 1]['swipes'].length) { //if swipe id of last message is the same as the length of the 'swipes' array | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ const extension_settings = { | |||||||
|     tts: {}, |     tts: {}, | ||||||
|     sd: {}, |     sd: {}, | ||||||
|     chromadb: {}, |     chromadb: {}, | ||||||
|  |     translate: {}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| let modules = []; | let modules = []; | ||||||
|   | |||||||
							
								
								
									
										248
									
								
								public/scripts/extensions/translate/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								public/scripts/extensions/translate/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,248 @@ | |||||||
|  | import { eventSource, event_types, getRequestHeaders, messageFormatting, saveSettingsDebounced } from "../../../script.js"; | ||||||
|  | import { extension_settings, getContext } from "../../extensions.js"; | ||||||
|  |  | ||||||
|  | const defaultSettings = { | ||||||
|  |     target_language: 'en', | ||||||
|  |     provider: 'google', | ||||||
|  |     auto: false, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const languageCodes = { | ||||||
|  |     'Afrikaans': 'af', | ||||||
|  |     'Albanian': 'sq', | ||||||
|  |     'Amharic': 'am', | ||||||
|  |     'Arabic': 'ar', | ||||||
|  |     'Armenian': 'hy', | ||||||
|  |     'Azerbaijani': 'az', | ||||||
|  |     'Basque': 'eu', | ||||||
|  |     'Belarusian': 'be', | ||||||
|  |     'Bengali': 'bn', | ||||||
|  |     'Bosnian': 'bs', | ||||||
|  |     'Bulgarian': 'bg', | ||||||
|  |     'Catalan': 'ca', | ||||||
|  |     'Cebuano': 'ceb', | ||||||
|  |     'Chinese (Simplified)': 'zh-CN', | ||||||
|  |     'Chinese (Traditional)': 'zh-TW', | ||||||
|  |     'Corsican': 'co', | ||||||
|  |     'Croatian': 'hr', | ||||||
|  |     'Czech': 'cs', | ||||||
|  |     'Danish': 'da', | ||||||
|  |     'Dutch': 'nl', | ||||||
|  |     'English': 'en', | ||||||
|  |     'Esperanto': 'eo', | ||||||
|  |     'Estonian': 'et', | ||||||
|  |     'Finnish': 'fi', | ||||||
|  |     'French': 'fr', | ||||||
|  |     'Frisian': 'fy', | ||||||
|  |     'Galician': 'gl', | ||||||
|  |     'Georgian': 'ka', | ||||||
|  |     'German': 'de', | ||||||
|  |     'Greek': 'el', | ||||||
|  |     'Gujarati': 'gu', | ||||||
|  |     'Haitian Creole': 'ht', | ||||||
|  |     'Hausa': 'ha', | ||||||
|  |     'Hawaiian': 'haw', | ||||||
|  |     'Hebrew': 'iw', | ||||||
|  |     'Hindi': 'hi', | ||||||
|  |     'Hmong': 'hmn', | ||||||
|  |     'Hungarian': 'hu', | ||||||
|  |     'Icelandic': 'is', | ||||||
|  |     'Igbo': 'ig', | ||||||
|  |     'Indonesian': 'id', | ||||||
|  |     'Irish': 'ga', | ||||||
|  |     'Italian': 'it', | ||||||
|  |     'Japanese': 'ja', | ||||||
|  |     'Javanese': 'jw', | ||||||
|  |     'Kannada': 'kn', | ||||||
|  |     'Kazakh': 'kk', | ||||||
|  |     'Khmer': 'km', | ||||||
|  |     'Korean': 'ko', | ||||||
|  |     'Kurdish': 'ku', | ||||||
|  |     'Kyrgyz': 'ky', | ||||||
|  |     'Lao': 'lo', | ||||||
|  |     'Latin': 'la', | ||||||
|  |     'Latvian': 'lv', | ||||||
|  |     'Lithuanian': 'lt', | ||||||
|  |     'Luxembourgish': 'lb', | ||||||
|  |     'Macedonian': 'mk', | ||||||
|  |     'Malagasy': 'mg', | ||||||
|  |     'Malay': 'ms', | ||||||
|  |     'Malayalam': 'ml', | ||||||
|  |     'Maltese': 'mt', | ||||||
|  |     'Maori': 'mi', | ||||||
|  |     'Marathi': 'mr', | ||||||
|  |     'Mongolian': 'mn', | ||||||
|  |     'Myanmar (Burmese)': 'my', | ||||||
|  |     'Nepali': 'ne', | ||||||
|  |     'Norwegian': 'no', | ||||||
|  |     'Nyanja (Chichewa)': 'ny', | ||||||
|  |     'Pashto': 'ps', | ||||||
|  |     'Persian': 'fa', | ||||||
|  |     'Polish': 'pl', | ||||||
|  |     'Portuguese (Portugal, Brazil)': 'pt', | ||||||
|  |     'Punjabi': 'pa', | ||||||
|  |     'Romanian': 'ro', | ||||||
|  |     'Russian': 'ru', | ||||||
|  |     'Samoan': 'sm', | ||||||
|  |     'Scots Gaelic': 'gd', | ||||||
|  |     'Serbian': 'sr', | ||||||
|  |     'Sesotho': 'st', | ||||||
|  |     'Shona': 'sn', | ||||||
|  |     'Sindhi': 'sd', | ||||||
|  |     'Sinhala (Sinhalese)': 'si', | ||||||
|  |     'Slovak': 'sk', | ||||||
|  |     'Slovenian': 'sl', | ||||||
|  |     'Somali': 'so', | ||||||
|  |     'Spanish': 'es', | ||||||
|  |     'Sundanese': 'su', | ||||||
|  |     'Swahili': 'sw', | ||||||
|  |     'Swedish': 'sv', | ||||||
|  |     'Tagalog (Filipino)': 'tl', | ||||||
|  |     'Tajik': 'tg', | ||||||
|  |     'Tamil': 'ta', | ||||||
|  |     'Telugu': 'te', | ||||||
|  |     'Thai': 'th', | ||||||
|  |     'Turkish': 'tr', | ||||||
|  |     'Ukrainian': 'uk', | ||||||
|  |     'Urdu': 'ur', | ||||||
|  |     'Uzbek': 'uz', | ||||||
|  |     'Vietnamese': 'vi', | ||||||
|  |     'Welsh': 'cy', | ||||||
|  |     'Xhosa': 'xh', | ||||||
|  |     'Yiddish': 'yi', | ||||||
|  |     'Yoruba': 'yo', | ||||||
|  |     'Zulu': 'zu', | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | function loadSettings() { | ||||||
|  |     if (Object.keys(extension_settings.translate).length === 0) { | ||||||
|  |         Object.assign(extension_settings.translate, defaultSettings); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $(`#translation_provider option[value="${extension_settings.translate.provider}"]`).attr('selected', true); | ||||||
|  |     $(`#translation_target_language option[value="${extension_settings.translate.target_language}"]`).attr('selected', true); | ||||||
|  |     $('#translation_auto').prop('checked', extension_settings.translate.auto); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function translateIncomingMessage(messageId) { | ||||||
|  |     const context = getContext(); | ||||||
|  |     const message = context.chat[messageId]; | ||||||
|  |  | ||||||
|  |     if (typeof message.extra !== 'object') { | ||||||
|  |         message.extra = {}; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // New swipe is being generated. Don't translate that | ||||||
|  |     if ($(`#chat .mes[mesid="${messageId}"] .mes_text`).text() == '...') { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const translation = await translate(message.mes); | ||||||
|  |     message.extra.display_text = translation; | ||||||
|  |  | ||||||
|  |     $(`#chat .mes[mesid="${messageId}"] .mes_text`).html(messageFormatting(translation, message.name, message.is_system, message.is_user)); | ||||||
|  |  | ||||||
|  |     context.saveChat(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function translateProviderGoogle(text) { | ||||||
|  |     const response = await fetch('/google_translate', { | ||||||
|  |         method: 'POST', | ||||||
|  |         headers: getRequestHeaders(), | ||||||
|  |         body: JSON.stringify({ text: text, lang: extension_settings.translate.target_language }), | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     if (response.ok) { | ||||||
|  |         const result = await response.text(); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     throw new Error(response.statusText); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function translate(text) { | ||||||
|  |     try { | ||||||
|  |         switch (extension_settings.translate.provider) { | ||||||
|  |             case 'google': | ||||||
|  |                 return await translateProviderGoogle(text); | ||||||
|  |             default: | ||||||
|  |                 console.error('Unknown translation provider', extension_settings.translate.provider); | ||||||
|  |                 return text; | ||||||
|  |         } | ||||||
|  |     } catch (error) { | ||||||
|  |         console.log(error); | ||||||
|  |         toastr.error('Failed to translate message'); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function translateOutgoingMessage(messageId) { | ||||||
|  |     alert('translateOutgoingMessage', messageId); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | jQuery(() => { | ||||||
|  |     const html = ` | ||||||
|  |     <div class="translation_settings"> | ||||||
|  |         <div class="inline-drawer"> | ||||||
|  |             <div class="inline-drawer-toggle inline-drawer-header"> | ||||||
|  |                 <b>Chat Translation</b> | ||||||
|  |                 <div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div> | ||||||
|  |             </div> | ||||||
|  |             <div class="inline-drawer-content"> | ||||||
|  |                 <label for="translation_auto" class="checkbox_label"> | ||||||
|  |                     <input type="checkbox" id="translation_auto" /> | ||||||
|  |                     Auto-mode | ||||||
|  |                 </label> | ||||||
|  |                 <label for="translation_provider">Provider</label> | ||||||
|  |                 <select id="translation_provider" name="provider"> | ||||||
|  |                     <option value="google">Google</option> | ||||||
|  |                 <select> | ||||||
|  |                 <label for="translation_target_language">Target Language</label> | ||||||
|  |                 <select id="translation_target_language" name="target_language"></select> | ||||||
|  |             </div> | ||||||
|  |         </div> | ||||||
|  |     </div>`; | ||||||
|  |  | ||||||
|  |     $('#extensions_settings').append(html); | ||||||
|  |     for (const [key, value] of Object.entries(languageCodes)) { | ||||||
|  |         $('#translation_target_language').append(`<option value="${value}">${key}</option>`); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     loadSettings(); | ||||||
|  |     eventSource.on(event_types.MESSAGE_RECEIVED, async (messageId) => { | ||||||
|  |         if (!extension_settings.translate.auto) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         await translateIncomingMessage(messageId); | ||||||
|  |     }); | ||||||
|  |     eventSource.on(event_types.MESSAGE_SWIPED, async (messageId) => { | ||||||
|  |         if (!extension_settings.translate.auto) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         await translateIncomingMessage(messageId); | ||||||
|  |     }); | ||||||
|  |     eventSource.on(event_types.MESSAGE_SENT, async (messageId) => { | ||||||
|  |         if (!extension_settings.translate.auto) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         await translateOutgoingMessage(messageId); | ||||||
|  |     }); | ||||||
|  |     $('#translation_auto').on('input', (event) => { | ||||||
|  |         extension_settings.translate.auto = event.target.checked; | ||||||
|  |         saveSettingsDebounced(); | ||||||
|  |     }); | ||||||
|  |     $('#translation_provider').on('change', (event) => { | ||||||
|  |         extension_settings.translate.provider = event.target.value; | ||||||
|  |         saveSettingsDebounced(); | ||||||
|  |     }); | ||||||
|  |     $('#translation_target_language').on('change', (event) => { | ||||||
|  |         extension_settings.translate.target_language = event.target.value; | ||||||
|  |         saveSettingsDebounced(); | ||||||
|  |     }); | ||||||
|  |     $(document).on('click', '.mes_translate', function () { | ||||||
|  |         const messageId = $(this).closest('.mes').attr('mesid'); | ||||||
|  |         translateIncomingMessage(messageId); | ||||||
|  |     }); | ||||||
|  |     document.body.classList.add('translate'); | ||||||
|  | }); | ||||||
							
								
								
									
										11
									
								
								public/scripts/extensions/translate/manifest.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								public/scripts/extensions/translate/manifest.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | { | ||||||
|  |     "display_name": "Chat Translation", | ||||||
|  |     "loading_order": 10, | ||||||
|  |     "requires": [], | ||||||
|  |     "optional": [], | ||||||
|  |     "js": "index.js", | ||||||
|  |     "css": "style.css", | ||||||
|  |     "author": "Cohee#1207", | ||||||
|  |     "version": "1.0.0", | ||||||
|  |     "homePage": "https://github.com/Cohee1207/SillyTavern" | ||||||
|  | } | ||||||
							
								
								
									
										0
									
								
								public/scripts/extensions/translate/style.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								public/scripts/extensions/translate/style.css
									
									
									
									
									
										Normal file
									
								
							| @@ -233,6 +233,7 @@ table.responsiveTable { | |||||||
|     text-align: center; |     text-align: center; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .mes_translate, | ||||||
| .sd_message_gen, | .sd_message_gen, | ||||||
| .mes_narrate, | .mes_narrate, | ||||||
| body.tts .mes[is_user="true"] .mes_narrate, | body.tts .mes[is_user="true"] .mes_narrate, | ||||||
| @@ -266,6 +267,7 @@ body.tts .mes[is_system="true"] .mes_narrate { | |||||||
| } | } | ||||||
|  |  | ||||||
| body.sd .sd_message_gen, | body.sd .sd_message_gen, | ||||||
|  | body.translate .mes_translate, | ||||||
| body.tts .mes_narrate { | body.tts .mes_narrate { | ||||||
|     display: inline-block; |     display: inline-block; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								server.js
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								server.js
									
									
									
									
									
								
							| @@ -2975,6 +2975,39 @@ app.post('/horde_generateimage', jsonParser, async (request, response) => { | |||||||
|     } |     } | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | app.post('/google_translate', jsonParser, async (request, response) => { | ||||||
|  |     const { generateRequestUrl, normaliseResponse } = require('google-translate-api-browser'); | ||||||
|  |     const https = require('https'); | ||||||
|  |  | ||||||
|  |     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); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  |  | ||||||
| function writeSecret(key, value) { | function writeSecret(key, value) { | ||||||
|     if (!fs.existsSync(SECRETS_FILE)) { |     if (!fs.existsSync(SECRETS_FILE)) { | ||||||
|         const emptyFile = JSON.stringify({}); |         const emptyFile = JSON.stringify({}); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user