bing-translate-api
Advanced tools
Comparing version 2.8.0 to 2.9.0
{ | ||
"name": "bing-translate-api", | ||
"version": "2.8.0", | ||
"version": "2.9.0", | ||
"description": "A simple and free API for Bing Translator for Node.js", | ||
@@ -9,3 +9,4 @@ "main": "src/index.js", | ||
"test": "node test/index.js && node test/lang.js", | ||
"gen:langmap": "node scripts/generate-lang-map.js" | ||
"gen:langmap": "node scripts/generate-lang-map.js", | ||
"gen:dts": "node scripts/generate-dts.js" | ||
}, | ||
@@ -37,3 +38,3 @@ "keywords": [ | ||
"dependencies": { | ||
"got": "^11.8.5" | ||
"got": "^11.8.6" | ||
}, | ||
@@ -40,0 +41,0 @@ "devDependencies": { |
@@ -22,3 +22,3 @@ # bing-translate-api | ||
translate('你好', null, 'en', true).then(res => { | ||
translate('你好', null, 'en').then(res => { | ||
console.log(res.translation); | ||
@@ -70,2 +70,3 @@ }).catch(err => { | ||
The language code of source text. | ||
**MUST** be `auto-detect` or one of the codes/names (not case sensitive) contained in [lang.json](https://github.com/plainheart/bing-translate-api/blob/master/src/lang.json) | ||
@@ -77,2 +78,3 @@ | ||
The language in which the text should be translated. | ||
**MUST** be one of the codes/names (not case sensitive) contained in [lang.json](https://github.com/plainheart/bing-translate-api/blob/master/src/lang.json). | ||
@@ -101,3 +103,3 @@ | ||
``` | ||
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 | ||
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 | ||
``` | ||
@@ -104,0 +106,0 @@ |
126
src/index.js
@@ -11,5 +11,5 @@ /** | ||
const TRANSLATE_API = TRANSLATE_API_ROOT + '/ttranslatev3?isVertical=1' | ||
const TRANSLATE_SPELL_CHECK_API = TRANSLATE_API_ROOT + '/tspellcheckv3?isVertical=1' | ||
const TRANSLATE_API_SPELL_CHECK = TRANSLATE_API_ROOT + '/tspellcheckv3?isVertical=1' | ||
const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36' | ||
const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36' | ||
@@ -21,3 +21,27 @@ // PENDING: fetch from `params_RichTranslate`? | ||
/** | ||
* @typedef {{ | ||
* IG: string, | ||
* IID: string, | ||
* subdomain?: string, | ||
* cookie: string, | ||
* key: number, | ||
* token: string, | ||
* tokenTs: number, | ||
* tokenExpiryInterval: number, | ||
* count: number | ||
* }} GlobalConfig | ||
* | ||
* @typedef {import('../index').TranslationResult} TranslationResult | ||
* | ||
* @typedef {import('got').Agents} GotAgents | ||
*/ | ||
/** | ||
* @type {GlobalConfig | undefined} | ||
*/ | ||
let globalConfig | ||
/** | ||
* @type {Promise<GlobalConfig> | undefined} | ||
*/ | ||
let globalConfigPromise | ||
@@ -42,34 +66,61 @@ | ||
/** | ||
* fetch global config including `IG`, `IID`, `token`, `key`, `tokenTs`, `tokenExpiryInterval` and `cookie` | ||
* fetch global config | ||
* | ||
* @param {string} userAgent | ||
* @param {import('got').Agents} proxyAgents | ||
* @param {GotAgents} proxyAgents | ||
* | ||
* @returns {Promise<GlobalConfig>} | ||
*/ | ||
async function fetchGlobalConfig(userAgent, proxyAgents) { | ||
let subdomain | ||
let IG | ||
let IID | ||
let token | ||
let key | ||
let tokenExpiryInterval | ||
let cookie | ||
// use last subdomain if exists | ||
let subdomain = globalConfig && globalConfig.subdomain | ||
try { | ||
const { body, headers, request: { redirects } } = await got(replaceSubdomain(TRANSLATE_WEBSITE, subdomain), { | ||
headers: { | ||
'user-agent': userAgent || USER_AGENT | ||
}, | ||
agent: proxyAgents | ||
}) | ||
const { body, headers, request: { redirects: [redirectUrl] } } = await got( | ||
replaceSubdomain(TRANSLATE_WEBSITE, subdomain), | ||
{ | ||
headers: { | ||
'user-agent': userAgent || USER_AGENT | ||
}, | ||
agent: proxyAgents | ||
} | ||
) | ||
subdomain = redirects[0].match(/^https?:\/\/(\w+)\.bing\.com/)[1] | ||
// when fetching for the second time, the subdomain may be unchanged | ||
if (redirectUrl) { | ||
subdomain = redirectUrl.match(/^https?:\/\/(\w+)\.bing\.com/)[1] | ||
} | ||
// PENDING: optional? | ||
cookie = headers['set-cookie'].map(c => c.split(';')[0]).join('; ') | ||
const cookie = headers['set-cookie'].map(c => c.split(';')[0]).join('; ') | ||
IG = body.match(/IG:"([^"]+)"/)[1] | ||
IID = body.match(/data-iid="([^"]+)"/)[1] | ||
const IG = body.match(/IG:"([^"]+)"/)[1] | ||
const IID = body.match(/data-iid="([^"]+)"/)[1] | ||
// required | ||
;[key, token, tokenExpiryInterval] = JSON.parse( | ||
const [key, token, tokenExpiryInterval] = JSON.parse( | ||
body.match(/params_AbusePreventionHelper\s?=\s?([^\]]+\])/)[1] | ||
) | ||
const requiredFields = { | ||
IG, | ||
IID, | ||
key, | ||
token, | ||
tokenTs: key, | ||
tokenExpiryInterval | ||
} | ||
// check required fields | ||
Object.entries(requiredFields).forEach(([field, value]) => { | ||
if (!value) { | ||
throw new Error(`failed to fetch required field: \`${field}\``) | ||
} | ||
}) | ||
return globalConfig = { | ||
...requiredFields, | ||
subdomain, | ||
cookie, | ||
// PENDING: reset count when value is large? | ||
count: 0 | ||
} | ||
} catch (e) { | ||
@@ -79,14 +130,2 @@ console.error('failed to fetch global config', e) | ||
} | ||
return globalConfig = { | ||
subdomain, | ||
IG, | ||
IID, | ||
key, | ||
token, | ||
tokenTs: key, | ||
tokenExpiryInterval, | ||
cookie, | ||
// PENDING: reset count if count value is large? | ||
count: 0 | ||
} | ||
} | ||
@@ -96,5 +135,5 @@ | ||
const { IG, IID, subdomain } = globalConfig | ||
return replaceSubdomain(isSpellCheck ? TRANSLATE_SPELL_CHECK_API : TRANSLATE_API, subdomain) | ||
+ (IG && IG.length ? '&IG=' + IG : '') | ||
+ (IID && IID.length ? '&IID=' + IID + '.' + (++globalConfig.count) : '') | ||
return replaceSubdomain(isSpellCheck ? TRANSLATE_API_SPELL_CHECK : TRANSLATE_API, subdomain) | ||
+ '&IG=' + IG | ||
+ '&IID=' + (IID + '.' + (++globalConfig.count)) | ||
} | ||
@@ -120,8 +159,10 @@ | ||
* @param {string} text content to be translated | ||
* @param {string} from <optional> source language code. `auto-detect` by default. | ||
* @param {string} to <optional> target language code. `en` by default. | ||
* @param {string} from source language code. `auto-detect` by default. | ||
* @param {string} to target language code. `en` by default. | ||
* @param {boolean} correct <optional> whether to correct the input text. `false` by default. | ||
* @param {boolean} raw <optional> the result contains raw response if `true` | ||
* @param {string} userAgent <optional> the expected user agent header | ||
* @param {import('got').Agents} proxyAgents <optional> set agents of `got` for proxy | ||
* @param {GotAgents} proxyAgents <optional> set agents of `got` for proxy | ||
* | ||
* @returns {Promise<TranslationResult>} | ||
*/ | ||
@@ -201,2 +242,5 @@ async function translate(text, from, to, correct, raw, userAgent, proxyAgents) { | ||
/** | ||
* @type {TranslationResult} | ||
*/ | ||
const res = { | ||
@@ -203,0 +247,0 @@ text, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
22922
656
115
Updatedgot@^11.8.6