UNPKG

@deeplx/core

Version:

An unofficial but powerful and easy-to-use yet free DeepL API client for Node.js using [DeepL](https://www.deepl.com) by porting [OwO-Network/DeepLX](https://github.com/OwO-Network/DeepLX).

419 lines (412 loc) 13.9 kB
'use strict'; var node_crypto = require('node:crypto'); var proxy = require('node-fetch-native/proxy'); var xFetch = require('x-fetch'); var __defProp$1 = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols; var __hasOwnProp$1 = Object.prototype.hasOwnProperty; var __propIsEnum$1 = Object.prototype.propertyIsEnumerable; var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$1 = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$1.call(b, prop)) __defNormalProp$1(a, prop, b[prop]); if (__getOwnPropSymbols$1) for (var prop of __getOwnPropSymbols$1(b)) { if (__propIsEnum$1.call(b, prop)) __defNormalProp$1(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); const SUPPORTED_LANGUAGES = [ { code: "AR", language: "Arabic" }, { code: "BG", language: "Bulgarian" }, { code: "CS", language: "Czech" }, { code: "DA", language: "Danish" }, { code: "DE", language: "German" }, { code: "EL", language: "Greek" }, { code: "EN", language: "English" }, { code: "EN-GB", language: "English (British)" }, { code: "EN-US", language: "English (American)" }, { code: "ES", language: "Spanish" }, { code: "ES-419", language: "Spanish (Latin American)" }, { code: "ET", language: "Estonian" }, { code: "FI", language: "Finnish" }, { code: "FR", language: "French" }, { code: "HE", language: "Hebrew" }, { code: "HU", language: "Hungarian" }, { code: "ID", language: "Indonesian" }, { code: "IT", language: "Italian" }, { code: "JA", language: "Japanese" }, { code: "KO", language: "Korean" }, { code: "LT", language: "Lithuanian" }, { code: "LV", language: "Latvian" }, { code: "NB", language: "Norwegian Bokm\xE5l" }, { code: "NL", language: "Dutch" }, { code: "PL", language: "Polish" }, { code: "PT", language: "Portuguese" }, { code: "PT-BR", language: "Portuguese (Brazilian)" }, { code: "PT-PT", language: "Portuguese (European)" }, { code: "RO", language: "Romanian" }, { code: "RU", language: "Russian" }, { code: "SK", language: "Slovak" }, { code: "SL", language: "Slovenian" }, { code: "SV", language: "Swedish" }, { code: "TR", language: "Turkish" }, { code: "UK", language: "Ukrainian" }, { code: "VI", language: "Vietnamese" }, { code: "ZH", language: "Chinese" }, { code: "ZH-HANS", language: "Chinese (Simplified)" }, { code: "ZH-HANT", language: "Chinese (Traditional)" } ]; const ONESHOT_FREE_ENDPOINT = "https://oneshot-free.www.deepl.com/v1/translate"; const ONESHOT_PRO_ENDPOINT = "https://oneshot-pro.www.deepl.com/v1/translate"; const IMPERSONATED_CHROME_MAJOR = "120"; const CHROME_EXTENSION_VERSION = "1.86.0"; const CHROME_EXTENSION_ID = "cofdbpoegempjloogbagkncekinflcnj"; const MAX_FREE_TEXT_LENGTH = 1500; const HTTP_STATUS_OK = 200; const HTTP_STATUS_BAD_REQUEST = 400; const HTTP_STATUS_NOT_FOUND = 404; const HTTP_STATUS_NOT_ALLOWED = 405; const HTTP_STATUS_PAYLOAD_TOO_LARGE = 413; const HTTP_STATUS_TOO_MANY_REQUESTS = 429; const HTTP_STATUS_INTERNAL_ERROR = 500; const HTTP_STATUS_SERVICE_UNAVAILABLE = 503; const TARGET_LANG_MAP = { AR: "ar", BG: "bg", CS: "cs", DA: "da", DE: "de", EL: "el", "EN-GB": "en-GB", "EN-US": "en-US", ES: "es", "ES-419": "es-419", ET: "et", FI: "fi", FR: "fr", HE: "he", HU: "hu", ID: "id", IT: "it", JA: "ja", KO: "ko", LT: "lt", LV: "lv", NB: "nb", NL: "nl", PL: "pl", "PT-BR": "pt-BR", "PT-PT": "pt-PT", RO: "ro", RU: "ru", SK: "sk", SL: "sl", SV: "sv", TR: "tr", UK: "uk", VI: "vi", ZH: "zh-Hans", "ZH-HANS": "zh-Hans", "ZH-HANT": "zh-Hant", EN: "en-US", PT: "pt-BR" }; const SOURCE_LANG_MAP = __spreadProps(__spreadValues$1({}, TARGET_LANG_MAP), { EN: "en", PT: "pt" }); let abbreviateLanguageDictionary; function getAbbreviateLanguages() { return abbreviateLanguageDictionary != null ? abbreviateLanguageDictionary : abbreviateLanguageDictionary = SUPPORTED_LANGUAGES.reduce( (acc, lang) => { acc[lang.code.toLowerCase()] = lang.code; acc[lang.language.toLowerCase()] = lang.code; return acc; }, {} ); } function abbreviateLanguage(language) { return getAbbreviateLanguages()[language.split("-")[0].toLowerCase()]; } var __defProp = Object.defineProperty; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __async$1 = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; let instanceID_; function getInstanceID() { return instanceID_ != null ? instanceID_ : instanceID_ = node_crypto.randomUUID(); } let sharedCookies = ""; let warmupPromise = null; function getSharedCookies() { return sharedCookies; } function warmCookies(proxyUrl) { return __async$1(this, null, function* () { if (warmupPromise !== null) { return warmupPromise; } warmupPromise = (() => __async$1(null, null, function* () { try { const res = yield xFetch.xfetch("https://www.deepl.com/translator", __spreadValues({ type: null }, proxy.createProxy({ url: proxyUrl }))); const setCookie = res.headers.get("set-cookie"); if (setCookie) { const cookies = []; const userCountryMatch = /userCountry=[^;]+/.exec(setCookie); if (userCountryMatch) { cookies.push(userCountryMatch[0]); } const verifiedBotMatch = /verifiedBot=[^;]+/.exec(setCookie); if (verifiedBotMatch) { cookies.push(verifiedBotMatch[0]); } if (cookies.length > 0) { sharedCookies = cookies.join("; "); } } } catch (e) { warmupPromise = null; } }))(); return warmupPromise; }); } function resolveLang(code, kind) { if (!code || code.toLowerCase() === "auto") { if (kind === "target") { return { success: false, error: 'target_lang cannot be "auto" or empty' }; } return { success: true, value: void 0 }; } const langMap = kind === "target" ? TARGET_LANG_MAP : SOURCE_LANG_MAP; const upperCode = code.toUpperCase(); let mapped = langMap[upperCode]; if (!mapped) { const abbreviated = abbreviateLanguage(code); if (abbreviated) { mapped = langMap[abbreviated.toUpperCase()]; } } if (!mapped) { return { success: false, error: `unsupported ${kind}_lang "${code}"` }; } return { success: true, value: mapped }; } function parseTranslationError(error, reqId) { if (error instanceof xFetch.ResponseError) { const status = error.response.status; if (status === HTTP_STATUS_TOO_MANY_REQUESTS) { return { code: status, id: reqId, message: "too many requests, ..." }; } return { code: status, id: reqId, message: error.message }; } return { code: HTTP_STATUS_SERVICE_UNAVAILABLE, id: reqId, message: String(error) }; } function buildHeaders(dlSession, requestCookies) { const authValue = dlSession ? `Bearer ${dlSession}` : "None"; const headers = { "Content-Type": "application/json", Accept: "*/*", Authorization: authValue, Origin: `chrome-extension://${CHROME_EXTENSION_ID}`, "Sec-Fetch-Site": "cross-site", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Dest": "empty", "Accept-Encoding": "gzip, deflate, br", "User-Agent": `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${IMPERSONATED_CHROME_MAJOR}.0.0.0 Safari/537.36` }; if (requestCookies) { headers["Cookie"] = requestCookies; } else if (sharedCookies) { headers["Cookie"] = sharedCookies; } return headers; } function processTranslationResponse(response, reqId, sourceLang, targetLang, dlSession) { if (!(response == null ? void 0 : response.translations) || response.translations.length === 0) { return { code: HTTP_STATUS_SERVICE_UNAVAILABLE, id: reqId, message: "Translation failed" }; } const mainTranslation = response.translations[0]; if (!mainTranslation.text) { return { code: HTTP_STATUS_SERVICE_UNAVAILABLE, id: reqId, message: "Translation failed" }; } const detectedLang = mainTranslation.detected_source_language ? mainTranslation.detected_source_language.toUpperCase() : sourceLang || "auto"; return { code: HTTP_STATUS_OK, id: reqId, data: mainTranslation.text, alternatives: [], sourceLang: detectedLang, targetLang, method: dlSession ? "Pro" : "Free" }; } const translateByDeepLX = (sourceLang, targetLang, text, proxyUrl, dlSession, signal, skipWarm, cookies) => __async$1(null, null, function* () { if (!text) { return { code: HTTP_STATUS_NOT_FOUND, message: "No text to translate" }; } if ([...text].length > MAX_FREE_TEXT_LENGTH) { return { code: HTTP_STATUS_PAYLOAD_TOO_LARGE, // Payload Too Large message: `text exceeds maximum length: ${[...text].length} characters (anonymous oneshot limit is ${MAX_FREE_TEXT_LENGTH})` }; } let requestCookies = cookies; if (!requestCookies && !dlSession && !skipWarm) { yield warmCookies(proxyUrl); requestCookies = sharedCookies; } const targetResult = resolveLang(targetLang, "target"); if (!targetResult.success) { return { code: HTTP_STATUS_BAD_REQUEST, message: targetResult.error }; } const sourceResult = resolveLang(sourceLang, "source"); if (!sourceResult.success) { return { code: HTTP_STATUS_BAD_REQUEST, message: sourceResult.error }; } const reqData = { text: [text], target_lang: targetResult.value, source_lang: sourceResult.value, usage_type: "Translate", app_information: { os: "brex_macOS", os_version: `brex_chrome_${IMPERSONATED_CHROME_MAJOR}.0.0.0`, app_version: CHROME_EXTENSION_VERSION, app_build: "chrome_web_store", instance_id: getInstanceID() } }; const reqId = Date.now(); try { const response = yield xFetch.xfetch( dlSession ? ONESHOT_PRO_ENDPOINT : ONESHOT_FREE_ENDPOINT, __spreadValues({ method: "POST", body: reqData, headers: buildHeaders(dlSession, requestCookies), signal }, proxy.createProxy({ url: proxyUrl })) ); return processTranslationResponse( response, reqId, sourceLang, targetLang, dlSession ); } catch (error) { return parseTranslationError(error, reqId); } }); var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; const translate = (text, targetLang, sourceLang, options) => __async(null, null, function* () { const result = yield translateByDeepLX( sourceLang, targetLang, text, options == null ? void 0 : options.proxyUrl, options == null ? void 0 : options.dlSession, options == null ? void 0 : options.signal, options == null ? void 0 : options.skipWarm, options == null ? void 0 : options.cookies ); if ("message" in result) { throw new Error(result.message, { cause: result }); } return result.data; }); exports.CHROME_EXTENSION_ID = CHROME_EXTENSION_ID; exports.CHROME_EXTENSION_VERSION = CHROME_EXTENSION_VERSION; exports.HTTP_STATUS_BAD_REQUEST = HTTP_STATUS_BAD_REQUEST; exports.HTTP_STATUS_INTERNAL_ERROR = HTTP_STATUS_INTERNAL_ERROR; exports.HTTP_STATUS_NOT_ALLOWED = HTTP_STATUS_NOT_ALLOWED; exports.HTTP_STATUS_NOT_FOUND = HTTP_STATUS_NOT_FOUND; exports.HTTP_STATUS_OK = HTTP_STATUS_OK; exports.HTTP_STATUS_PAYLOAD_TOO_LARGE = HTTP_STATUS_PAYLOAD_TOO_LARGE; exports.HTTP_STATUS_SERVICE_UNAVAILABLE = HTTP_STATUS_SERVICE_UNAVAILABLE; exports.HTTP_STATUS_TOO_MANY_REQUESTS = HTTP_STATUS_TOO_MANY_REQUESTS; exports.IMPERSONATED_CHROME_MAJOR = IMPERSONATED_CHROME_MAJOR; exports.MAX_FREE_TEXT_LENGTH = MAX_FREE_TEXT_LENGTH; exports.ONESHOT_FREE_ENDPOINT = ONESHOT_FREE_ENDPOINT; exports.ONESHOT_PRO_ENDPOINT = ONESHOT_PRO_ENDPOINT; exports.SOURCE_LANG_MAP = SOURCE_LANG_MAP; exports.SUPPORTED_LANGUAGES = SUPPORTED_LANGUAGES; exports.TARGET_LANG_MAP = TARGET_LANG_MAP; exports.abbreviateLanguage = abbreviateLanguage; exports.getSharedCookies = getSharedCookies; exports.translate = translate; exports.translateByDeepLX = translateByDeepLX;