Merge branch 'main' of https://github.com/kwaroran/RisuAI
This commit is contained in:
@@ -3,12 +3,11 @@ const app = express();
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const htmlparser = require('node-html-parser');
|
const htmlparser = require('node-html-parser');
|
||||||
const { existsSync, mkdirSync, readFileSync, writeFileSync } = require('fs');
|
const { existsSync, mkdirSync, readFileSync, writeFileSync } = require('fs');
|
||||||
const bodyParser = require('body-parser');
|
|
||||||
const fs = require('fs/promises')
|
const fs = require('fs/promises')
|
||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
app.use(express.static(path.join(process.cwd(), 'dist'), {index: false}));
|
app.use(express.static(path.join(process.cwd(), 'dist'), {index: false}));
|
||||||
app.use(bodyParser.raw({ limit: 100000000 }));
|
app.use(express.json({ limit: '50mb' }));
|
||||||
app.use(bodyParser.json())
|
app.use(express.raw({ type: 'application/octet-stream', limit: '50mb' }));
|
||||||
const {pipeline} = require('stream/promises')
|
const {pipeline} = require('stream/promises')
|
||||||
|
|
||||||
let password = ''
|
let password = ''
|
||||||
@@ -90,6 +89,55 @@ const reverseProxyFunc = async (req, res, next) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const reverseProxyFunc_get = async (req, res, next) => {
|
||||||
|
const urlParam = req.headers['risu-url'] ? decodeURIComponent(req.headers['risu-url']) : req.query.url;
|
||||||
|
|
||||||
|
if (!urlParam) {
|
||||||
|
res.status(400).send({
|
||||||
|
error:'URL has no param'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const header = req.headers['risu-header'] ? JSON.parse(decodeURIComponent(req.headers['risu-header'])) : req.headers;
|
||||||
|
if(!header['x-forwarded-for']){
|
||||||
|
header['x-forwarded-for'] = req.ip
|
||||||
|
}
|
||||||
|
let originalResponse;
|
||||||
|
try {
|
||||||
|
// make request to original server
|
||||||
|
originalResponse = await fetch(urlParam, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: header
|
||||||
|
});
|
||||||
|
// get response body as stream
|
||||||
|
const originalBody = originalResponse.body;
|
||||||
|
// get response headers
|
||||||
|
const head = new Headers(originalResponse.headers);
|
||||||
|
head.delete('content-security-policy');
|
||||||
|
head.delete('content-security-policy-report-only');
|
||||||
|
head.delete('clear-site-data');
|
||||||
|
head.delete('Cache-Control');
|
||||||
|
head.delete('Content-Encoding');
|
||||||
|
const headObj = {};
|
||||||
|
for (let [k, v] of head) {
|
||||||
|
headObj[k] = v;
|
||||||
|
}
|
||||||
|
// send response headers to client
|
||||||
|
res.header(headObj);
|
||||||
|
// send response status to client
|
||||||
|
res.status(originalResponse.status);
|
||||||
|
// send response body to client
|
||||||
|
await pipeline(originalResponse.body, res);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
next(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
app.get('/proxy', reverseProxyFunc_get);
|
||||||
|
app.get('/proxy2', reverseProxyFunc_get);
|
||||||
|
|
||||||
app.post('/proxy', reverseProxyFunc);
|
app.post('/proxy', reverseProxyFunc);
|
||||||
app.post('/proxy2', reverseProxyFunc);
|
app.post('/proxy2', reverseProxyFunc);
|
||||||
|
|
||||||
|
|||||||
@@ -117,6 +117,21 @@
|
|||||||
<TextAreaInput bind:value={$DataBase.translatorPrompt} placeholder={"You are a translator. translate the following html or text into {{slot}}. do not output anything other than the translation."}/>
|
<TextAreaInput bind:value={$DataBase.translatorPrompt} placeholder={"You are a translator. translate the following html or text into {{slot}}. do not output anything other than the translation."}/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if $DataBase.translatorType === 'google'}
|
||||||
|
<span class="text-textcolor mt-4">Translator Input Language</span>
|
||||||
|
<SelectInput className="mt-2 mb-4" bind:value={$DataBase.translatorInputLanguage}>
|
||||||
|
<OptionInput value="auto">Auto</OptionInput>
|
||||||
|
<OptionInput value="en">English</OptionInput>
|
||||||
|
<OptionInput value="zh">Chinese</OptionInput>
|
||||||
|
<OptionInput value="ja">Japanese</OptionInput>
|
||||||
|
<OptionInput value="ko">Korean</OptionInput>
|
||||||
|
<OptionInput value="fr">French</OptionInput>
|
||||||
|
<OptionInput value="es">Spanish</OptionInput>
|
||||||
|
<OptionInput value="de">German</OptionInput>
|
||||||
|
<OptionInput value="ru">Russian</OptionInput>
|
||||||
|
</SelectInput>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
<div class="flex items-center mt-2">
|
<div class="flex items-center mt-2">
|
||||||
<Check bind:check={$DataBase.autoTranslate} name={language.autoTranslation}/>
|
<Check bind:check={$DataBase.autoTranslate} name={language.autoTranslation}/>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
import Button from "src/lib/UI/GUI/Button.svelte";
|
import Button from "src/lib/UI/GUI/Button.svelte";
|
||||||
import { getCharImage } from "src/ts/characters";
|
import { getCharImage } from "src/ts/characters";
|
||||||
import Arcodion from "src/lib/UI/Arcodion.svelte";
|
import Arcodion from "src/lib/UI/Arcodion.svelte";
|
||||||
|
import CheckInput from "src/lib/UI/GUI/CheckInput.svelte";
|
||||||
$:{
|
$:{
|
||||||
$DataBase.NAIImgConfig ??= {
|
$DataBase.NAIImgConfig ??= {
|
||||||
width: 512,
|
width: 512,
|
||||||
@@ -299,6 +300,9 @@
|
|||||||
|
|
||||||
{#if submenu === 1 || submenu === -1}
|
{#if submenu === 1 || submenu === -1}
|
||||||
<Arcodion name="TTS" styled disabled={submenu !== -1}>
|
<Arcodion name="TTS" styled disabled={submenu !== -1}>
|
||||||
|
<span class="text-textcolor mt-2">Auto Speech</span>
|
||||||
|
<CheckInput bind:check={$DataBase.ttsAutoSpeech}/>
|
||||||
|
|
||||||
<span class="text-textcolor mt-2">ElevenLabs API key</span>
|
<span class="text-textcolor mt-2">ElevenLabs API key</span>
|
||||||
<TextInput size="sm" marginBottom bind:value={$DataBase.elevenLabKey}/>
|
<TextInput size="sm" marginBottom bind:value={$DataBase.elevenLabKey}/>
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,13 @@
|
|||||||
if (!(currentChar.data as character).gptSoVitsConfig.use_prompt) {
|
if (!(currentChar.data as character).gptSoVitsConfig.use_prompt) {
|
||||||
(currentChar.data as character).gptSoVitsConfig.prompt = undefined
|
(currentChar.data as character).gptSoVitsConfig.prompt = undefined
|
||||||
}
|
}
|
||||||
|
if((currentChar.data as character).gptSoVitsConfig.use_auto_path){
|
||||||
|
(currentChar.data as character).gptSoVitsConfig.ref_audio_path = undefined;
|
||||||
|
|
||||||
|
(currentChar.data as character).gptSoVitsConfig.use_prompt = false;
|
||||||
|
(currentChar.data as character).gptSoVitsConfig.prompt = undefined;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -160,7 +167,9 @@
|
|||||||
$: if (currentChar.data.ttsMode === 'gptsovits' && (currentChar.data as character).gptSoVitsConfig === undefined) {
|
$: if (currentChar.data.ttsMode === 'gptsovits' && (currentChar.data as character).gptSoVitsConfig === undefined) {
|
||||||
(currentChar.data as character).gptSoVitsConfig = {
|
(currentChar.data as character).gptSoVitsConfig = {
|
||||||
url: '',
|
url: '',
|
||||||
ref_audio_path: 'C:/Users/user/Downloads/GPT-SoVITS-v2-240821',
|
use_auto_path: false,
|
||||||
|
ref_audio_path: '',
|
||||||
|
use_long_audio: false,
|
||||||
ref_audio_data: {
|
ref_audio_data: {
|
||||||
fileName: '',
|
fileName: '',
|
||||||
assetId: ''
|
assetId: ''
|
||||||
@@ -835,15 +844,24 @@
|
|||||||
<span class="text-textcolor">URL</span>
|
<span class="text-textcolor">URL</span>
|
||||||
<TextInput className="mb-4 mt-2" bind:value={currentChar.data.gptSoVitsConfig.url}/>
|
<TextInput className="mb-4 mt-2" bind:value={currentChar.data.gptSoVitsConfig.url}/>
|
||||||
|
|
||||||
|
<span class="text-textcolor">Use Auto Path</span>
|
||||||
|
<Check bind:check={currentChar.data.gptSoVitsConfig.use_auto_path}/>
|
||||||
|
|
||||||
|
{#if !currentChar.data.gptSoVitsConfig.use_auto_path}
|
||||||
<span class="text-textcolor">Reference Audio Path (e.g. C:/Users/user/Downloads/GPT-SoVITS-v2-240821)</span>
|
<span class="text-textcolor">Reference Audio Path (e.g. C:/Users/user/Downloads/GPT-SoVITS-v2-240821)</span>
|
||||||
<TextInput className="mb-4 mt-2" bind:value={currentChar.data.gptSoVitsConfig.ref_audio_path}/>
|
<TextInput className="mb-4 mt-2" bind:value={currentChar.data.gptSoVitsConfig.ref_audio_path}/>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<span class="text-textcolor">Use Long Audio</span>
|
||||||
|
<Check bind:check={currentChar.data.gptSoVitsConfig.use_long_audio}/>
|
||||||
|
|
||||||
<span class="text-textcolor">Reference Audio Data (3~10s audio file)</span>
|
<span class="text-textcolor">Reference Audio Data (3~10s audio file)</span>
|
||||||
<Button on:click={async () => {
|
<Button on:click={async () => {
|
||||||
const audio = await selectSingleFile([
|
const audio = await selectSingleFile([
|
||||||
'wav',
|
'wav',
|
||||||
'ogg',
|
'ogg',
|
||||||
'aac'
|
'aac',
|
||||||
|
'mp3'
|
||||||
])
|
])
|
||||||
if(!audio){
|
if(!audio){
|
||||||
return null
|
return null
|
||||||
@@ -866,40 +884,42 @@
|
|||||||
</Button>
|
</Button>
|
||||||
<span class="text-textcolor">Text Language</span>
|
<span class="text-textcolor">Text Language</span>
|
||||||
<SelectInput className="mb-4 mt-2" bind:value={currentChar.data.gptSoVitsConfig.text_lang}>
|
<SelectInput className="mb-4 mt-2" bind:value={currentChar.data.gptSoVitsConfig.text_lang}>
|
||||||
<OptionInput value="auto">Auto</OptionInput>
|
<OptionInput value="auto">Multi-language Mixed</OptionInput>
|
||||||
<OptionInput value="auto_yue">Auto (Cantonese)</OptionInput>
|
<OptionInput value="auto_yue">Multi-language Mixed (Cantonese)</OptionInput>
|
||||||
<OptionInput value="en">English</OptionInput>
|
<OptionInput value="en">English</OptionInput>
|
||||||
<OptionInput value="zh">Chinese</OptionInput>
|
<OptionInput value="zh">Chinese-English Mixed</OptionInput>
|
||||||
<OptionInput value="ja">Japanese</OptionInput>
|
<OptionInput value="ja">Japanese-English Mixed</OptionInput>
|
||||||
<OptionInput value="yue">Cantonese</OptionInput>
|
<OptionInput value="yue">Cantonese-English Mixed</OptionInput>
|
||||||
<OptionInput value="ko">Korean</OptionInput>
|
<OptionInput value="ko">Korean-English Mixed</OptionInput>
|
||||||
<OptionInput value="all_zh">All Chinese</OptionInput>
|
<OptionInput value="all_zh">Chinese</OptionInput>
|
||||||
<OptionInput value="all_ja">All Japanese</OptionInput>
|
<OptionInput value="all_ja">Japanese</OptionInput>
|
||||||
<OptionInput value="all_yue">All Cantonese</OptionInput>
|
<OptionInput value="all_yue">Cantonese</OptionInput>
|
||||||
<OptionInput value="all_ko">All Korean</OptionInput>
|
<OptionInput value="all_ko">Korean</OptionInput>
|
||||||
</SelectInput>
|
</SelectInput>
|
||||||
|
|
||||||
|
{#if !currentChar.data.gptSoVitsConfig.use_long_audio}
|
||||||
<span class="text-textcolor">Use Reference Audio Script</span>
|
<span class="text-textcolor">Use Reference Audio Script</span>
|
||||||
<Check bind:check={currentChar.data.gptSoVitsConfig.use_prompt}/>
|
<Check bind:check={currentChar.data.gptSoVitsConfig.use_prompt}/>
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if currentChar.data.gptSoVitsConfig.use_prompt}
|
{#if currentChar.data.gptSoVitsConfig.use_prompt && !currentChar.data.gptSoVitsConfig.use_long_audio}
|
||||||
<span class="text-textcolor">Reference Audio Script</span>
|
<span class="text-textcolor">Reference Audio Script</span>
|
||||||
<TextAreaInput className="mb-4 mt-2" bind:value={currentChar.data.gptSoVitsConfig.prompt}/>
|
<TextAreaInput className="mb-4 mt-2" bind:value={currentChar.data.gptSoVitsConfig.prompt}/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<span class="text-textcolor">Reference Audio Language</span>
|
<span class="text-textcolor">Reference Audio Language</span>
|
||||||
<SelectInput className="mb-4 mt-2" bind:value={currentChar.data.gptSoVitsConfig.prompt_lang}>
|
<SelectInput className="mb-4 mt-2" bind:value={currentChar.data.gptSoVitsConfig.prompt_lang}>
|
||||||
<OptionInput value="auto">Auto</OptionInput>
|
<OptionInput value="auto">Multi-language Mixed</OptionInput>
|
||||||
<OptionInput value="auto_yue">Auto (Cantonese)</OptionInput>
|
<OptionInput value="auto_yue">Multi-language Mixed (Cantonese)</OptionInput>
|
||||||
<OptionInput value="en">English</OptionInput>
|
<OptionInput value="en">English</OptionInput>
|
||||||
<OptionInput value="zh">Chinese</OptionInput>
|
<OptionInput value="zh">Chinese-English Mixed</OptionInput>
|
||||||
<OptionInput value="ja">Japanese</OptionInput>
|
<OptionInput value="ja">Japanese-English Mixed</OptionInput>
|
||||||
<OptionInput value="yue">Cantonese</OptionInput>
|
<OptionInput value="yue">Cantonese-English Mixed</OptionInput>
|
||||||
<OptionInput value="ko">Korean</OptionInput>
|
<OptionInput value="ko">Korean-English Mixed</OptionInput>
|
||||||
<OptionInput value="all_zh">English And Chinese</OptionInput>
|
<OptionInput value="all_zh">Chinese</OptionInput>
|
||||||
<OptionInput value="all_ja">English And Japanese</OptionInput>
|
<OptionInput value="all_ja">Japanese</OptionInput>
|
||||||
<OptionInput value="all_yue">English And Cantonese</OptionInput>
|
<OptionInput value="all_yue">Cantonese</OptionInput>
|
||||||
<OptionInput value="all_ko">English And Korean</OptionInput>
|
<OptionInput value="all_ko">Korean</OptionInput>
|
||||||
</SelectInput>
|
</SelectInput>
|
||||||
<span class="text-textcolor">Top P</span>
|
<span class="text-textcolor">Top P</span>
|
||||||
<SliderInput min={0.0} max={1.0} step={0.05} fixed={2} bind:value={currentChar.data.gptSoVitsConfig.top_p}/>
|
<SliderInput min={0.0} max={1.0} step={0.05} fixed={2} bind:value={currentChar.data.gptSoVitsConfig.top_p}/>
|
||||||
|
|||||||
@@ -1181,8 +1181,10 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n
|
|||||||
db.characters[selectedChar].chats[selectedChat] = currentChat
|
db.characters[selectedChar].chats[selectedChat] = currentChat
|
||||||
setDatabase(db)
|
setDatabase(db)
|
||||||
}
|
}
|
||||||
|
if(db.ttsAutoSpeech){
|
||||||
await sayTTS(currentChar, result)
|
await sayTTS(currentChar, result)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else{
|
else{
|
||||||
const msgs = (req.type === 'success') ? [['char',req.result]] as const
|
const msgs = (req.type === 'success') ? [['char',req.result]] as const
|
||||||
: (req.type === 'multiline') ? req.result
|
: (req.type === 'multiline') ? req.result
|
||||||
@@ -1240,7 +1242,9 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n
|
|||||||
mrerolls.push(result)
|
mrerolls.push(result)
|
||||||
}
|
}
|
||||||
db.characters[selectedChar].reloadKeys += 1
|
db.characters[selectedChar].reloadKeys += 1
|
||||||
|
if(db.ttsAutoSpeech){
|
||||||
await sayTTS(currentChar, result)
|
await sayTTS(currentChar, result)
|
||||||
|
}
|
||||||
setDatabase(db)
|
setDatabase(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ export async function sayTTS(character:character,text:string) {
|
|||||||
const body = {
|
const body = {
|
||||||
text: text,
|
text: text,
|
||||||
text_lang: character.gptSoVitsConfig.text_lang,
|
text_lang: character.gptSoVitsConfig.text_lang,
|
||||||
ref_audio_path: character.gptSoVitsConfig.ref_audio_path + '/public/audio/' + character.gptSoVitsConfig.ref_audio_data.fileName,
|
ref_audio_path: undefined,
|
||||||
ref_audio_name: character.gptSoVitsConfig.ref_audio_data.fileName,
|
ref_audio_name: character.gptSoVitsConfig.ref_audio_data.fileName,
|
||||||
ref_audio_data: base64Audio,
|
ref_audio_data: base64Audio,
|
||||||
prompt_text: undefined,
|
prompt_text: undefined,
|
||||||
@@ -250,18 +250,41 @@ export async function sayTTS(character:character,text:string) {
|
|||||||
speed_factor: character.gptSoVitsConfig.speed,
|
speed_factor: character.gptSoVitsConfig.speed,
|
||||||
top_k: character.gptSoVitsConfig.top_k,
|
top_k: character.gptSoVitsConfig.top_k,
|
||||||
text_split_method: character.gptSoVitsConfig.text_split_method,
|
text_split_method: character.gptSoVitsConfig.text_split_method,
|
||||||
parallel_infer: false,
|
parallel_infer: true,
|
||||||
|
// media_type: character.gptSoVitsConfig.ref_audio_data.fileName.split('.')[1],
|
||||||
|
ref_free: character.gptSoVitsConfig.use_long_audio || !character.gptSoVitsConfig.use_prompt,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (character.gptSoVitsConfig.use_prompt){
|
if (character.gptSoVitsConfig.use_prompt){
|
||||||
body.prompt_text = character.gptSoVitsConfig.prompt
|
body.prompt_text = character.gptSoVitsConfig.prompt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (character.gptSoVitsConfig.use_auto_path){
|
||||||
|
console.log('auto')
|
||||||
|
const path = await globalFetch(`${character.gptSoVitsConfig.url}/get_path`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
rawResponse: false,
|
||||||
|
|
||||||
|
})
|
||||||
|
console.log(path)
|
||||||
|
if(path.ok){
|
||||||
|
body.ref_audio_path = path.data.message + '/public/audio/' + character.gptSoVitsConfig.ref_audio_data.fileName
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
throw new Error('Failed to Auto get path')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
body.ref_audio_path = character.gptSoVitsConfig.ref_audio_path + '/public/audio/' + character.gptSoVitsConfig.ref_audio_data.fileName
|
||||||
|
}
|
||||||
console.log(body)
|
console.log(body)
|
||||||
|
|
||||||
const response = await globalFetch(`${character.gptSoVitsConfig.url}/tts`, {
|
const response = await globalFetch(`${character.gptSoVitsConfig.url}/tts`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: body,
|
body: body,
|
||||||
rawResponse: true,
|
rawResponse: true,
|
||||||
|
|||||||
@@ -430,7 +430,8 @@ export function setDatabase(data:Database){
|
|||||||
}
|
}
|
||||||
data.hideApiKey ??= true
|
data.hideApiKey ??= true
|
||||||
data.unformatQuotes ??= false
|
data.unformatQuotes ??= false
|
||||||
|
data.ttsAutoSpeech ??= false
|
||||||
|
data.translatorInputLanguage ??= 'auto'
|
||||||
changeLanguage(data.language)
|
changeLanguage(data.language)
|
||||||
DataBase.set(data)
|
DataBase.set(data)
|
||||||
}
|
}
|
||||||
@@ -510,6 +511,7 @@ export interface Database{
|
|||||||
NAII2I:boolean
|
NAII2I:boolean
|
||||||
NAIREF:boolean
|
NAIREF:boolean
|
||||||
NAIImgConfig:NAIImgConfig
|
NAIImgConfig:NAIImgConfig
|
||||||
|
ttsAutoSpeech?:boolean
|
||||||
runpodKey:string
|
runpodKey:string
|
||||||
promptPreprocess:boolean
|
promptPreprocess:boolean
|
||||||
bias: [string, number][]
|
bias: [string, number][]
|
||||||
@@ -614,6 +616,7 @@ export interface Database{
|
|||||||
emotionProcesser:'submodel'|'embedding',
|
emotionProcesser:'submodel'|'embedding',
|
||||||
showMenuChatList?:boolean,
|
showMenuChatList?:boolean,
|
||||||
translatorType:'google'|'deepl'|'none'|'llm'|'deeplX',
|
translatorType:'google'|'deepl'|'none'|'llm'|'deeplX',
|
||||||
|
translatorInputLanguage?:string
|
||||||
NAIadventure?:boolean,
|
NAIadventure?:boolean,
|
||||||
NAIappendName?:boolean,
|
NAIappendName?:boolean,
|
||||||
deeplOptions:{
|
deeplOptions:{
|
||||||
@@ -809,7 +812,9 @@ export interface character{
|
|||||||
}
|
}
|
||||||
gptSoVitsConfig?:{
|
gptSoVitsConfig?:{
|
||||||
url?:string
|
url?:string
|
||||||
|
use_auto_path?:boolean
|
||||||
ref_audio_path?:string
|
ref_audio_path?:string
|
||||||
|
use_long_audio?:boolean
|
||||||
ref_audio_data?: {
|
ref_audio_data?: {
|
||||||
fileName:string
|
fileName:string
|
||||||
assetId:string
|
assetId:string
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ async function translateMain(text:string, arg:{from:string, to:string, host:stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const url = `https://${arg.host}/translate_a/single?client=gtx&dt=t&sl=auto&tl=${arg.to}&q=` + encodeURIComponent(text)
|
const url = `https://${arg.host}/translate_a/single?client=gtx&dt=t&sl=${db.translatorInputLanguage}&tl=${arg.to}&q=` + encodeURIComponent(text)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user