illyria-scraper
Version:
Google Translate scraper for Illyria Translate
101 lines • 4.05 kB
JavaScript
import axios, {} from 'axios';
import UserAgent from 'user-agents';
export const Endpoint = {
INFO: 'info',
TEXT: 'text',
AUDIO: 'audio'
};
/**
* Creates a request handler for a specific endpoint with built-in retry capabilities
*
* @param endpoint - The API endpoint to call
* @param retry - Current retry attempt number (used internally)
* @returns An object with methods to execute the request
*/
const request = (endpoint, retry = 0) => ({
with: (params) => {
const promise = retrieve(endpoint, params);
return {
promise,
/**
* Executes a callback with the response data and handles errors/retries
*
* @param callback - Function to process the API response
* @returns Promise resolving to the callback result or null on failure
*/
doing: (callback) => promise
.then((response) => {
const result = callback(response);
// Check if result is empty and we haven't exceeded max retries
if (isEmpty(result) && retry < 3) {
console.warn(`Empty result for ${endpoint}, retrying (${retry + 1}/3)`);
return request(endpoint, retry + 1)
.with(params)
.doing(callback);
}
return result ?? null;
})
.catch((error) => {
if (error.response) {
console.error(`${endpoint} failed:`, error.response.status, error.response.data);
}
else if (error.request) {
console.error(`${endpoint} network error:`, error.message);
}
else {
console.error(`${endpoint} error:`, error.message);
}
// Only retry for network errors or 5xx status codes
const shouldRetry = !error.response || error.response.status >= 500;
if (shouldRetry && retry < 3) {
console.warn(`Retrying ${endpoint} after error (${retry + 1}/3)`);
return request(endpoint, retry + 1)
.with(params)
.doing(callback);
}
return null;
})
};
}
});
const isEmpty = (item) => !item || (Array.isArray(item) && item.length === 0);
/**
* Makes the actual HTTP request to the specified endpoint
*
* @param endpoint - The API endpoint to call
* @param params - Parameters required by the endpoint
* @returns Promise resolving to the API response
* @throws Error if an invalid endpoint is provided
*/
const retrieve = (endpoint, params) => {
const userAgent = new UserAgent().toString();
const baseConfig = {
headers: { 'User-Agent': userAgent },
timeout: 30000
};
if (endpoint === Endpoint.INFO) {
const { body } = params;
return axios.post('https://translate.google.com/_/TranslateWebserverUi/data/batchexecute?rpcids=MkEWBc&rt=c', body, {
...baseConfig,
headers: {
...baseConfig.headers,
'Content-Type': 'application/x-www-form-urlencoded'
}
});
}
if (endpoint === Endpoint.TEXT) {
const { source, target, query } = params;
return axios.get(`https://translate.google.com/m?sl=${source}&tl=${target}&q=${encodeURIComponent(query)}`, baseConfig);
}
if (endpoint === Endpoint.AUDIO) {
const { lang, text, textLength, speed } = params;
return axios.get(`https://translate.google.com/translate_tts?tl=${lang}&q=${encodeURIComponent(text)}&textlen=${textLength}&speed=${speed}&client=tw-ob`, {
...baseConfig,
responseType: 'arraybuffer',
timeout: 60000 // Audio needs more time
});
}
throw new Error(`Invalid endpoint: ${endpoint}`);
};
export default request;
//# sourceMappingURL=request.js.map