Skip to content

Commit

Permalink
feat: wrap request to provide more detailed and readable error message
Browse files Browse the repository at this point in the history
  • Loading branch information
plainheart committed Nov 18, 2023
1 parent c792c4e commit 4ee73b8
Showing 1 changed file with 94 additions and 54 deletions.
148 changes: 94 additions & 54 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,3 @@
/**
* @type {import('got').Got}
*/
const got = require('got')

const lang = require('./lang')
const config = require('./config.json')

const TRANSLATE_API_ROOT = 'https://{s}bing.com'
const TRANSLATE_WEBSITE = TRANSLATE_API_ROOT + config.websiteEndpoint
const TRANSLATE_API = TRANSLATE_API_ROOT + config.translateEndpoint
const TRANSLATE_API_SPELL_CHECK = TRANSLATE_API_ROOT + config.spellCheckEndpoint

// PENDING: make it configurable?
const MAX_RETRY_COUNT = 3

/**
* @typedef {{
* IG: string,
Expand All @@ -28,10 +12,31 @@ const MAX_RETRY_COUNT = 3
* }} GlobalConfig
*
* @typedef {import('../index').TranslationResult} TranslationResult
*
* @typedef {import('got').Got} Got
* @typedef {import('got').Options} GotOptions
* @typedef {import('got').Agents} GotAgents
* @typedef {import('got').CancelableRequest} GotCancelableRequest
* @typedef {import('got').Response} GotResponse
* @typedef {import('got').RequestError} GotRequestError
*/

/**
* @type {Got}
*/
const got = require('got')

const lang = require('./lang')
const config = require('./config.json')

const TRANSLATE_API_ROOT = 'https://{s}bing.com'
const TRANSLATE_WEBSITE = TRANSLATE_API_ROOT + config.websiteEndpoint
const TRANSLATE_API = TRANSLATE_API_ROOT + config.translateEndpoint
const TRANSLATE_API_SPELL_CHECK = TRANSLATE_API_ROOT + config.spellCheckEndpoint

// PENDING: make it configurable?
const MAX_RETRY_COUNT = 3

/**
* @type {GlobalConfig | undefined}
*/
Expand Down Expand Up @@ -60,8 +65,8 @@ function isTokenExpired() {
/**
* fetch global config
*
* @param {string} userAgent
* @param {GotAgents} proxyAgents
* @param {string?} [userAgent]
* @param {GotAgents?} [proxyAgents]
*
* @returns {Promise<GlobalConfig>}
*/
Expand Down Expand Up @@ -167,6 +172,56 @@ function makeRequestBody(isSpellCheck, text, fromLang, toLang) {
return body
}

/**
* @param {GotCancelableRequest} request
*/
async function wrapRequest(request) {
/**
* @type {GotResponse}
*/
let response
/**
* @type {GotRequestError}
*/
let err

try {
response = await request
} catch (e) {
response = (err = e).response
}

/**
* @type {string}
*/
let readableErrMsg

const body = response.body

if (body.ShowCaptcha) {
readableErrMsg = `Sorry that bing translator seems to be asking for the captcha, please take care not to request too frequently.`
}
else if (body.StatusCode === 401 || response.statusCode === 401) {
readableErrMsg = `Translation limit exceeded. Please try it again later.`
}
else if (body.statusCode) {
readableErrMsg = `Something went wrong!`
}

if (readableErrMsg) {
const responseMsg = `Response URL: ${response.url}\nResponse status: ${response.statusCode} (${response.statusMessage})\nResponse body : ${JSON.stringify(body)}`
throw new Error(readableErrMsg + '\n' + responseMsg)
}

if (err) {
const wrappedErr = new Error(`Failed to request translation service`)
wrappedErr.stack += '\n' + err.stack
throw wrappedErr
}

return body
}

/**
* To translate
*
Expand Down Expand Up @@ -224,40 +279,23 @@ async function translate(text, from, to, correct, raw, userAgent, proxyAgents) {
}

/**
* @type {import('got').Options['retry']}
* @type {GotOptions['retry']}
*/
const retryConfig = {
limit: MAX_RETRY_COUNT,
methods: ['POST']
}

const { body } = await got.post(requestURL, {
headers: requestHeaders,
// got will set CONTENT_TYPE as `application/x-www-form-urlencoded`
form: requestBody,
responseType: 'json',
agent: proxyAgents,
retry: retryConfig
})

if (body.ShowCaptcha) {
throw new Error(`
Sorry that bing translator seems to be asking for the captcha,
Please take care not to request too frequently.
The response code is ${body.StatusCode}.
`)
}

if (body.StatusCode === 401) {
throw new Error(`
Max count of translation exceeded. Please try it again later.
The response code is 401.
`)
}

if (body.statusCode) {
throw new Error(`Something went wrong! The response is ${JSON.stringify(body)}.`)
}
const body = await wrapRequest(
got.post(requestURL, {
headers: requestHeaders,
// got will set CONTENT_TYPE as `application/x-www-form-urlencoded`$
form: requestBody,
responseType: 'json',
agent: proxyAgents,
retry: retryConfig
})
)

const translation = body[0].translations[0]
const detectedLang = body[0].detectedLanguage
Expand Down Expand Up @@ -287,13 +325,15 @@ async function translate(text, from, to, correct, raw, userAgent, proxyAgents) {
const requestURL = makeRequestURL(true)
const requestBody = makeRequestBody(true, text, correctLang)

const { body } = await got.post(requestURL, {
headers: requestHeaders,
form: requestBody,
responseType: 'json',
agent: proxyAgents,
retry: retryConfig
})
const body = await wrapRequest(
got.post(requestURL, {
headers: requestHeaders,
form: requestBody,
responseType: 'json',
agent: proxyAgents,
retry: retryConfig
})
)

res.correctedText = body && body.correctedText
}
Expand Down

0 comments on commit 4ee73b8

Please sign in to comment.