@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
JavaScript
;
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;