From 82b5c334e9af245c68020b98e3527a96c3148e2b Mon Sep 17 00:00:00 2001 From: Robert Vitonsky Date: Tue, 25 Jun 2024 03:35:01 +0200 Subject: [PATCH] feat: add free version of DeeplX translator --- src/translators/DeepLFreeTranslator/hosts.ts | 350 ++++++++++++++++++ src/translators/DeepLFreeTranslator/index.ts | 111 ++++++ src/translators/__tests__/translators.test.ts | 2 + 3 files changed, 463 insertions(+) create mode 100644 src/translators/DeepLFreeTranslator/hosts.ts create mode 100644 src/translators/DeepLFreeTranslator/index.ts diff --git a/src/translators/DeepLFreeTranslator/hosts.ts b/src/translators/DeepLFreeTranslator/hosts.ts new file mode 100644 index 0000000..a033c9a --- /dev/null +++ b/src/translators/DeepLFreeTranslator/hosts.ts @@ -0,0 +1,350 @@ +// Source: https://github.com/xiaozhou26/serch_deeplx/blob/b17f6107cd0c05c0ba7b0ca9cb530d5954c78db4/success_result.txt +export const freeHosts = [ + 'https://deeplx.vercel.app', + 'https://deeplx.papercar.top', + 'https://dlx.bitjss.com', + 'https://deeplx.ychinfo.com', + 'http://82.156.183.23:6000', + 'http://20.89.253.28', + 'http://152.70.126.168:802', + 'http://150.230.46.11:8089', + 'http://deepl.wuyongx.uk', + 'http://106.15.89.0:7001', + 'http://74.48.183.216:8082', + 'http://45.94.43.74:8082', + 'http://110.42.235.245:8811', + 'http://154.40.45.116:2000', + 'https://deepl.dlwlrma.xyz', + 'https://deeplx.spaceq.xyz', + 'https://dx-api.nosec.link', + 'https://deepl.coloo.org', + 'https://dx.ift.lat', + 'https://translate.dftianyi.com', + 'https://deeplx.keyrotate.com', + 'https://ghhosa.zzaning.com', + 'https://deepx.dumpit.top', + 'https://deepl.wuyongx.uk', + 'http://107.150.100.170:8880', + 'https://deepl.zhaosaipo.com', + 'https://deepl.aimoyu.tech', + 'https://deeplx.imward.dev', + 'https://deepl.tr1ck.cn', + 'https://deeplx.he-sb.top', + 'https://gpay.eu.org', + 'http://107.173.186.30:1188', + 'http://195.154.184.125:1188', + 'http://157.90.115.116:1188', + 'http://45.33.120.170:1188', + 'http://38.6.176.90:1024', + 'http://45.147.51.155:1188', + 'http://46.8.19.173:1188', + 'http://51.81.210.63:1188', + 'http://138.68.240.43:1188', + 'http://176.126.114.231:1188', + 'http://142.171.3.185:1188', + 'http://62.106.70.227:1188', + 'http://54.64.224.232:1188', + 'http://38.148.254.10:1188', + 'http://103.158.190.203:4321', + 'http://18.142.80.110:1188', + 'http://119.28.13.127:1188', + 'http://207.148.127.142:1188', + 'http://146.56.165.8:1188', + 'http://132.145.93.176:1188', + 'http://138.2.123.154:1188', + 'http://132.226.232.50:1188', + 'http://103.152.35.2:1188', + 'http://132.145.80.159:1188', + 'http://38.47.100.106:1188', + 'http://202.81.237.189:1188', + 'http://170.64.190.34:1188', + 'http://209.141.41.59:1188', + 'http://35.220.175.223:1188', + 'http://165.154.203.71:1188', + 'http://120.46.95.125:1188', + 'http://152.69.180.143:1188', + 'http://203.25.119.208:1188', + 'http://42.192.93.139:10003', + 'http://122.152.221.70:1188', + 'http://47.236.22.51:1188', + 'http://101.35.115.171:1188', + 'http://119.91.152.74:1188', + 'http://123.60.157.70:8085', + 'http://58.87.104.110:1188', + 'http://43.139.218.213:1188', + 'http://82.157.137.187:1188', + 'http://82.156.36.11:1188', + 'http://1.12.243.147:1188', + 'http://8.130.121.171:1188', + 'http://175.178.237.179:1188', + 'http://106.14.104.93:1188', + 'http://117.50.183.46:1188', + 'http://82.157.49.14:1188', + 'http://190.92.242.194:1188', + 'http://123.56.13.17:1188', + 'http://59.110.162.193:1188', + 'http://139.224.191.20:1188', + 'http://139.159.242.136:1188', + 'http://121.43.36.212:1188', + 'http://49.233.41.73:1188', + 'http://120.76.140.44:1188', + 'http://47.102.106.172:1188', + 'http://39.105.60.208:1188', + 'http://101.133.141.24:8188', + 'http://43.155.174.62:1188', + 'http://39.101.74.119:1188', + 'http://5.252.226.8:1188', + 'http://120.78.15.169:1188', + 'http://124.71.99.68:1188', + 'http://8.138.111.57:1188', + 'http://47.119.24.34:1188', + 'http://47.107.109.131:1188', + 'http://182.42.127.225:1188', + 'http://142.171.59.190:1188', + 'http://103.200.30.119:1188', + 'http://139.99.66.128:1188', + 'http://121.43.134.47:1188', + 'http://182.150.116.147:1188', + 'http://120.76.141.173:1188', + 'http://79.137.205.255:1188', + 'http://124.71.191.52:1188', + 'http://148.135.98.234:1188', + 'http://23.94.122.132:1188', + 'http://150.230.46.219:8136', + 'http://148.135.73.241:1188', + 'http://37.123.193.136:1188', + 'http://103.163.186.90:1188', + 'http://8.131.60.61:1188', + 'http://142.171.77.219:1188', + 'http://15.228.190.225:12294', + 'http://148.135.124.106:1188', + 'http://148.135.51.114:1188', + 'http://209.141.49.210:1188', + 'http://123.116.149.203:1188', + 'http://43.143.240.2:1188', + 'http://120.55.63.151:1188', + 'http://121.41.99.203:1188', + 'http://104.168.43.152:1188', + 'http://47.119.172.46:1188', + 'http://101.133.234.93:1188', + 'http://129.146.98.200:1188', + 'http://142.171.199.125:1188', + 'http://74.48.52.216:1188', + 'http://148.135.107.108:1188', + 'http://101.43.76.234:1188', + 'http://146.56.111.178:1188', + 'http://74.48.19.200:1188', + 'http://168.138.161.149:1188', + 'http://124.221.198.187:1188', + 'http://38.47.98.127:1188', + 'http://165.154.5.156:1188', + 'http://138.2.11.53:1188', + 'http://43.134.250.154:1188', + 'http://124.223.85.170:1188', + 'http://129.153.73.237:1188', + 'http://141.98.197.109:1188', + 'http://192.210.142.53:1188', + 'http://142.171.198.78:1188', + 'http://43.154.124.164:1188', + 'http://150.230.32.50:1188', + 'http://162.55.35.20:1188', + 'http://148.135.58.49:1188', + 'http://168.138.34.126:1188', + 'http://158.247.197.25:1188', + 'http://148.135.61.236:1188', + 'http://144.24.94.118:1188', + 'http://116.62.112.61:1188', + 'http://119.28.32.110:1188', + 'http://69.30.241.226:1188', + 'http://138.2.95.93:1188', + 'http://168.138.214.221:1188', + 'http://158.101.157.53:1188', + 'http://117.50.162.145:1188', + 'http://192.210.143.151:1188', + 'http://42.192.21.116:1188', + 'http://195.245.242.19:1188', + 'http://64.112.42.240:1188', + 'http://104.214.145.200:1188', + 'http://141.147.151.154:1188', + 'http://42.193.219.103:1188', + 'http://148.135.62.170:1188', + 'http://1.12.45.103:1188', + 'http://95.164.86.107:1188', + 'http://157.245.192.219:1188', + 'http://150.230.108.185:1188', + 'http://152.67.211.94:1188', + 'http://148.135.70.165:1188', + 'http://107.172.137.246:1188', + 'http://172.245.131.60:8081', + 'http://120.55.189.173:1188', + 'http://107.174.88.163:1188', + 'http://47.103.194.159:1188', + 'http://16.163.29.52:12294', + 'http://103.247.28.212:1188', + 'http://141.11.139.98:1188', + 'http://81.70.207.129:1188', + 'http://45.143.234.207:1188', + 'http://43.143.198.166:1188', + 'http://154.40.56.85:1188', + 'http://198.46.215.119:1188', + 'http://109.206.245.73:1188', + 'http://165.227.18.166:1188', + 'http://47.109.98.57:1188', + 'http://107.172.234.71:1188', + 'http://45.145.72.29:1188', + 'http://39.100.95.114:1188', + 'http://107.172.103.49:1188', + 'http://107.172.8.146:1188', + 'http://8.140.203.210:1188', + 'http://120.26.116.45:1188', + 'http://51.222.13.40:1188', + 'http://116.203.83.80:1188', + 'http://104.160.19.60:8000', + 'http://47.243.28.163:1188', + 'http://104.168.22.220:1188', + 'http://150.230.46.11:1188', + 'http://172.104.83.81:1188', + 'http://107.172.87.53:1188', + 'http://146.56.111.210:1188', + 'http://185.106.209.123:1188', + 'http://107.189.1.3:1188', + 'http://106.14.17.223:1188', + 'http://74.48.170.227:1188', + 'http://107.175.28.34:1188', + 'http://129.146.241.124:1188', + 'http://49.235.73.101:1188', + 'http://148.135.81.210:1188', + 'http://167.99.24.220:1188', + 'http://152.67.213.75:1188', + 'http://47.107.100.134:1188', + 'http://194.233.71.122:1188', + 'http://142.171.225.251:1188', + 'http://52.194.218.139:1188', + 'http://192.9.142.50:1188', + 'http://43.130.10.231:1188', + 'http://101.42.160.235:1188', + 'http://43.133.184.109:1188', + 'http://123.57.16.233:1188', + 'http://148.135.106.166:1188', + 'http://213.35.115.52:1188', + 'http://211.227.72.101:1188', + 'http://142.171.218.120:8000', + 'http://47.76.126.155:1188', + 'http://118.89.199.180:80', + 'http://47.76.48.116:1188', + 'http://144.24.84.231:1188', + 'http://119.91.23.165:1188', + 'http://120.79.93.103:1188', + 'http://142.171.12.29:1188', + 'http://150.230.254.8:9033', + 'http://146.56.97.135:1188', + 'http://23.94.104.174:1188', + 'http://107.175.28.239:1188', + 'http://8.142.134.155:1188', + 'http://107.173.255.75:7788', + 'http://106.14.72.237:1188', + 'http://43.143.233.18:1188', + 'http://37.123.196.26:1188', + 'http://8.222.213.133:1188', + 'http://47.242.206.190:1188', + 'http://103.117.103.14:1188', + 'http://139.224.225.116:1188', + 'http://150.230.200.159:1188', + 'http://89.117.172.208:1188', + 'http://45.152.67.153:1188', + 'http://18.157.122.228:1188', + 'http://43.134.189.147:1188', + 'http://192.9.145.2:1188', + 'http://121.43.165.38:1188', + 'http://104.234.60.178:1188', + 'http://124.220.101.194:1188', + 'http://52.140.204.252:1188', + 'http://192.227.249.132:1188', + 'http://142.171.218.100:1188', + 'http://192.9.147.173:1188', + 'http://120.77.245.55:1188', + 'http://43.132.160.253:1188', + 'http://101.43.224.133:1188', + 'http://23.94.223.217:1188', + 'http://101.201.38.103:1188', + 'http://193.32.149.239:1188', + 'http://20.89.43.13:1188', + 'http://103.114.163.230:1188', + 'http://43.154.208.219:1188', + 'http://120.78.82.181:1188', + 'http://141.11.139.95:1188', + 'http://155.248.187.32:1188', + 'http://193.32.151.19:1188', + 'http://47.236.38.78:1188', + 'http://124.222.168.113:1188', + 'http://104.208.71.189:1188', + 'http://34.97.37.189:1188', + 'http://168.138.161.222:1188', + 'http://42.98.172.229:1188', + 'http://101.43.100.100:1188', + 'http://116.252.28.28:1188', + 'http://39.105.97.161:1188', + 'http://81.70.94.105:1188', + 'http://8.142.90.128:1188', + 'http://150.158.80.45:6009', + 'http://139.159.254.35:1188', + 'http://146.56.111.132:8180', + 'http://150.158.45.100:1188', + 'http://159.75.240.245:1188', + 'http://101.35.175.93:1188', + 'http://47.116.37.52:1188', + 'http://194.87.252.161:1188', + 'http://153.36.242.81:10030', + 'http://20.205.96.238:1188', + 'http://8.210.101.225:1188', + 'http://114.55.7.143:1188', + 'http://39.107.101.134:1188', + 'http://119.3.6.116:1188', + 'http://110.42.225.114:1988', + 'http://43.156.58.228:1188', + 'http://8.134.151.104:1188', + 'http://141.11.90.131:1188', + 'http://37.123.192.81:1188', + 'http://142.171.224.118:1188', + 'http://74.48.163.250:1188', + 'https://e.nxnow.top', + 'http://142.171.26.166:1010', + 'http://146.235.18.76:9090', + 'http://142.171.74.214:1188', + 'http://88.151.33.155:8006', + 'http://61.224.93.19:1198', + 'http://38.175.193.59:1188', + 'http://158.180.64.131:1188', + 'http://59.35.154.192:1188', + 'http://8.222.185.96:1188', + 'http://43.138.46.231:1188', + 'http://107.174.255.56:1188', + 'http://ssk.wiki:1188', + 'https://dx.mmyy.fun', + 'http://124.222.158.199:1188', + 'http://154.23.244.83:1188', + 'http://101.201.151.226:1188', + 'http://59.110.34.163:85', + 'http://192.210.196.117:1188', + 'http://222.67.176.225:1188', + 'https://deeplx.qninq.cn', + 'https://deeplx.qiud.org', + 'http://101.42.227.165:1188', + 'http://18.183.159.207:1188', + 'http://www1.0860523.top:1188', + 'http://120.46.163.33:1188', + 'https://dxn.mmyy.fun', + 'http://111.231.53.79:1188', + 'http://13.213.64.250:1188', + 'https://shaw.mmyy.fun', + 'https://xyzlab.mmyy.fun', + 'https://154.18.161.26', + 'https://49.232.185.166', + 'https://89.208.240.50', + 'https://46.3.104.72', + 'http://138.2.124.103:1188', + 'http://223.240.172.245:1188', + 'http://149.104.27.140:1188', + 'https://150.158.96.53:3006', + 'http://222.90.149.175:1188', +]; diff --git a/src/translators/DeepLFreeTranslator/index.ts b/src/translators/DeepLFreeTranslator/index.ts new file mode 100644 index 0000000..a2e3100 --- /dev/null +++ b/src/translators/DeepLFreeTranslator/index.ts @@ -0,0 +1,111 @@ +import { langCode, langCodeWithAuto } from '../Translator'; +import { BaseTranslator, TranslatorOptions } from '../BaseTranslator'; +import { freeHosts } from './hosts'; + +export type DeepLTranslatorOptions = { + apiHost?: string; +}; + +const getRandomItem = (array: Array): T => { + const max = array.length; + const randomIndex = Math.floor(Math.random() * max); + return array[randomIndex]; +}; + +const filteredFreeHosts = freeHosts.filter( + (host) => host.startsWith('https') && /(\d+.){3}\d+/.test(host) === false, +); + +// TODO: fix `HTTPError: Response code 429 (Too Many Requests)`. We should call multiple servers +export class DeepLFreeTranslator extends BaseTranslator { + public static readonly translatorName = 'DeepLFreeTranslator'; + + public static isRequiredKey = () => false; + + public static isSupportedAutoFrom = () => true; + + public static getSupportedLanguages(): langCode[] { + // eslint-disable + // prettier-ignore + return [ + 'bg', 'cs', 'da', 'de', 'el', 'en', 'es', 'et', 'fi', 'fr', + 'hu', 'id', 'it', 'ja', 'ko', 'lt', 'lv', 'nb', 'nl', 'pl', + 'pt', 'ro', 'ru', 'sk', 'sl', 'sv', 'tr', 'uk', 'zh' + ]; + // eslint-enable + } + + private readonly apiHost; + constructor({ + apiHost = 'https://deeplx.vercel.app', + ...options + }: TranslatorOptions) { + super(options); + + this.apiHost = apiHost; + } + + public getLengthLimit() { + return 5000; + } + + public getRequestsTimeout() { + return 300; + } + + public checkLimitExceeding(text: string | string[]) { + if (Array.isArray(text)) { + const arrayLen = text.reduce((acc, text) => acc + text.length, 0); + const extra = arrayLen - this.getLengthLimit(); + return extra > 0 ? extra : 0; + } else { + const extra = text.length - this.getLengthLimit(); + return extra > 0 ? extra : 0; + } + } + + public async translate(text: string, from: langCodeWithAuto, to: langCode) { + const host = this.apiHost ?? getRandomItem(filteredFreeHosts); + + console.log('use host', host); + + const abortController = new AbortController(); + setTimeout(() => { + abortController.abort(new Error('Timeout')); + }, 5000); + + for (let retry = 0; retry < 8; retry++) { + if (abortController.signal.aborted) + throw ( + abortController.signal.reason ?? + new Error('Aborted with unknown reason') + ); + + const response = await this.fetch(`${host}/translate`, { + signal: abortController.signal, + responseType: 'json', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + ...this.options.headers, + }, + // eslint-disable-next-line camelcase + body: JSON.stringify({ text, source_lang: from, target_lang: to }), + }); + + // Try another host if not provided host. If provided, we must sent requests only there + if (!response.ok && !this.apiHost) continue; + + const data = response.data.data; + if (typeof data !== 'string') throw new Error('Bad response'); + + return data; + } + + throw new Error('Out of retries'); + } + + public async translateBatch(texts: string[], from: langCodeWithAuto, to: langCode) { + return Promise.all(texts.map((text) => this.translate(text, from, to))); + } +} diff --git a/src/translators/__tests__/translators.test.ts b/src/translators/__tests__/translators.test.ts index 8444b1b..bd32b5b 100644 --- a/src/translators/__tests__/translators.test.ts +++ b/src/translators/__tests__/translators.test.ts @@ -10,6 +10,7 @@ import { TartuNLPTranslator } from '../TartuNLPTranslator'; import { DeepLTranslator } from '../DeepLTranslator'; import { LibreTranslateTranslator } from '../unstable/LibreTranslateTranslator'; import { ReversoTranslator } from '../unstable/ReversoTranslator'; +import { DeepLFreeTranslator } from '../DeepLFreeTranslator'; const commonTranslatorOptions = { headers: { @@ -21,6 +22,7 @@ const commonTranslatorOptions = { // Verify types const translators: TranslatorConstructor[] = [ + DeepLFreeTranslator, GoogleTranslator, GoogleTranslatorTokenFree, YandexTranslator,