From 15a1a53d40305eadf7d1d7d8d4be27b4e1d84877 Mon Sep 17 00:00:00 2001 From: Sankarsan Kampa <19631364+k3rn31p4nic@users.noreply.github.com> Date: Thu, 7 May 2020 22:12:32 +0530 Subject: [PATCH] update refactor Signed-off-by: Sankarsan Kampa <19631364+k3rn31p4nic@users.noreply.github.com> --- src/index.js | 258 +++++++++++++++++++++--------------------- src/languages.js | 235 +++++++++++++++++++------------------- src/tokenGenerator.js | 145 +++++++++++------------- 3 files changed, 316 insertions(+), 322 deletions(-) diff --git a/src/index.js b/src/index.js index f706215..b892153 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ -const languages = require('./languages'); -const tokenGenerator = require('./tokenGenerator'); -const querystring = require('querystring'); -const got = require('got'); +const languages = require("./languages"); +const tokenGenerator = require("./tokenGenerator"); +const querystring = require("querystring"); +const got = require("got"); /** * @function translate @@ -10,144 +10,144 @@ const got = require('got'); * @returns {Object} The result containing the translation. */ async function translate(text, options) { - try { - if (typeof options !== 'object') options = {}; - text = String(text); - - // Check if a lanugage is in supported; if not, throw an error object. - let error; - [ options.from, options.to ].forEach((lang) => { - if (lang && !languages.isSupported(lang)) { - error = new Error(); - error.code = 400; - error.message = `The language '${lang}' is not supported.`; - } - }); - if (error) throw error; - - // If options object doesn't have 'from' language, set it to 'auto'. - if (!options.hasOwnProperty('from')) options.from = 'auto'; - // If options object doesn't have 'to' language, set it to 'en'. - if (!options.hasOwnProperty('to')) options.to = 'en'; - // If options object has a 'raw' property evaluating to true, set it to true. - options.raw = Boolean(options.raw); - - // Get ISO 639-1 codes for the languages. - options.from = languages.getISOCode(options.from); - options.to = languages.getISOCode(options.to); - - // Generate Google Translate token for the text to be translated. - let token = await tokenGenerator.generate(text); - - // URL & query string required by Google Translate. - let baseUrl = 'https://translate.google.com/translate_a/single'; - let data = { - client: 'gtx', - sl: options.from, - tl: options.to, - hl: options.to, - dt: [ 'at', 'bd', 'ex', 'ld', 'md', 'qca', 'rw', 'rm', 'ss', 't' ], - ie: 'UTF-8', - oe: 'UTF-8', - otf: 1, - ssel: 0, - tsel: 0, - kc: 7, - q: text, - [token.name]: token.value - }; - - // Append query string to the request URL. - let url = `${baseUrl}?${querystring.stringify(data)}`; - - let requestOptions; - // If request URL is greater than 2048 characters, use POST method. - if (url.length > 2048) { - delete data.q; - requestOptions = [ - `${baseUrl}?${querystring.stringify(data)}`, - { - method: 'POST', - form: true, - body: { - q: text - } + try { + if (typeof options !== "object") options = {}; + text = String(text); + + // Check if a lanugage is in supported; if not, throw an error object. + let error; + [ options.from, options.to ].forEach((lang) => { + if (lang && !languages.isSupported(lang)) { + error = new Error(); + error.code = 400; + error.message = `The language '${lang}' is not supported.`; + } + }); + if (error) throw error; + + // If options object doesn"t have "from" language, set it to "auto". + if (!Object.prototype.hasOwnProperty.call(options, "from")) options.from = "auto"; + // If options object doesn"t have "to" language, set it to "en". + if (!Object.prototype.hasOwnProperty.call(options, "to")) options.to = "en"; + // If options object has a "raw" property evaluating to true, set it to true. + options.raw = Boolean(options.raw); + + // Get ISO 639-1 codes for the languages. + options.from = languages.getISOCode(options.from); + options.to = languages.getISOCode(options.to); + + // Generate Google Translate token for the text to be translated. + let token = await tokenGenerator.generate(text); + + // URL & query string required by Google Translate. + let baseUrl = "https://translate.google.com/translate_a/single"; + let data = { + client: "gtx", + sl: options.from, + tl: options.to, + hl: options.to, + dt: [ "at", "bd", "ex", "ld", "md", "qca", "rw", "rm", "ss", "t" ], + ie: "UTF-8", + oe: "UTF-8", + otf: 1, + ssel: 0, + tsel: 0, + kc: 7, + q: text, + [token.name]: token.value + }; + + // Append query string to the request URL. + let url = `${baseUrl}?${querystring.stringify(data)}`; + + let requestOptions; + // If request URL is greater than 2048 characters, use POST method. + if (url.length > 2048) { + delete data.q; + requestOptions = [ + `${baseUrl}?${querystring.stringify(data)}`, + { + method: "POST", + form: true, + body: { + q: text + } + } + ]; + } + else { + requestOptions = [ url ]; } - ]; - } - else { - requestOptions = [ url ]; - } - // Request translation from Google Translate. - let response = await got(...requestOptions); - - let result = { - text: '', - from: { - language: { - didYouMean: false, - iso: '' - }, - text: { - autoCorrected: false, - value: '', - didYouMean: false + // Request translation from Google Translate. + let response = await got(...requestOptions); + + let result = { + text: "", + from: { + language: { + didYouMean: false, + iso: "" + }, + text: { + autoCorrected: false, + value: "", + didYouMean: false + } + }, + raw: "" + }; + + // If user requested a raw output, add the raw response to the result + if (options.raw) { + result.raw = response.body; } - }, - raw: '' - }; - // If user requested a raw output, add the raw response to the result - if (options.raw) { - result.raw = response.body; - } + // Parse string body to JSON and add it to result object. - // Parse string body to JSON and add it to result object. + let body = JSON.parse(response.body); + body[0].forEach((obj) => { + if (obj[0]) { + result.text += obj[0]; + } + }); - let body = JSON.parse(response.body); - body[0].forEach((obj) => { - if (obj[0]) { - result.text += obj[0]; - } - }); + if (body[2] === body[8][0][0]) { + result.from.language.iso = body[2]; + } + else { + result.from.language.didYouMean = true; + result.from.language.iso = body[8][0][0]; + } - if (body[2] === body[8][0][0]) { - result.from.language.iso = body[2]; - } - else { - result.from.language.didYouMean = true; - result.from.language.iso = body[8][0][0]; - } + if (body[7] && body[7][0]) { + let str = body[7][0]; - if (body[7] && body[7][0]) { - let str = body[7][0]; + str = str.replace(//g, "["); + str = str.replace(/<\/i><\/b>/g, "]"); - str = str.replace(//g, '['); - str = str.replace(/<\/i><\/b>/g, ']'); + result.from.text.value = str; - result.from.text.value = str; + if (body[7][5] === true) { + result.from.text.autoCorrected = true; + } + else { + result.from.text.didYouMean = true; + } + } - if (body[7][5] === true) { - result.from.text.autoCorrected = true; - } - else { - result.from.text.didYouMean = true; - } + return result; } - - return result; - } - catch (e) { - if (e.name === 'HTTPError') { - let error = new Error(); - error.name = e.name; - error.statusCode = e.statusCode; - error.statusMessage = e.statusMessage; - throw error; + catch (e) { + if (e.name === "HTTPError") { + let error = new Error(); + error.name = e.name; + error.statusCode = e.statusCode; + error.statusMessage = e.statusMessage; + throw error; + } + throw e; } - throw e; - } } module.exports = translate; diff --git a/src/languages.js b/src/languages.js index 3bb343f..3b2ed2a 100644 --- a/src/languages.js +++ b/src/languages.js @@ -1,117 +1,118 @@ /** * Generated from https://translate.google.com * - * The languages that Google Translate supports (as of 2/11/2018) alongside + * The languages that Google Translate supports (as of 7/5/2020) alongside * their ISO 639-1 codes - * See https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes + * @see https://cloud.google.com/translate/docs/languages + * @see https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes */ -let languages = { - 'auto': 'Automatic', - 'af': 'Afrikaans', - 'sq': 'Albanian', - 'am': 'Amharic', - 'ar': 'Arabic', - 'hy': 'Armenian', - 'az': 'Azerbaijani', - 'eu': 'Basque', - 'be': 'Belarusian', - 'bn': 'Bengali', - 'bs': 'Bosnian', - 'bg': 'Bulgarian', - 'ca': 'Catalan', - 'ceb': 'Cebuano', - 'ny': 'Chichewa', - 'zh-cn': 'Chinese Simplified', - 'zh-tw': 'Chinese Traditional', - 'co': 'Corsican', - 'hr': 'Croatian', - 'cs': 'Czech', - 'da': 'Danish', - 'nl': 'Dutch', - 'en': 'English', - 'eo': 'Esperanto', - 'et': 'Estonian', - 'tl': 'Filipino', - 'fi': 'Finnish', - 'fr': 'French', - 'fy': 'Frisian', - 'gl': 'Galician', - 'ka': 'Georgian', - 'de': 'German', - 'el': 'Greek', - 'gu': 'Gujarati', - 'ht': 'Haitian Creole', - 'ha': 'Hausa', - 'haw': 'Hawaiian', - 'iw': 'Hebrew', - 'hi': 'Hindi', - 'hmn': 'Hmong', - 'hu': 'Hungarian', - 'is': 'Icelandic', - 'ig': 'Igbo', - 'id': 'Indonesian', - 'ga': 'Irish', - 'it': 'Italian', - 'ja': 'Japanese', - 'jw': 'Javanese', - 'kn': 'Kannada', - 'kk': 'Kazakh', - 'km': 'Khmer', - 'ko': 'Korean', - 'ku': 'Kurdish (Kurmanji)', - 'ky': 'Kyrgyz', - 'lo': 'Lao', - 'la': 'Latin', - 'lv': 'Latvian', - 'lt': 'Lithuanian', - 'lb': 'Luxembourgish', - 'mk': 'Macedonian', - 'mg': 'Malagasy', - 'ms': 'Malay', - 'ml': 'Malayalam', - 'mt': 'Maltese', - 'mi': 'Maori', - 'mr': 'Marathi', - 'mn': 'Mongolian', - 'my': 'Myanmar (Burmese)', - 'ne': 'Nepali', - 'no': 'Norwegian', - 'ps': 'Pashto', - 'fa': 'Persian', - 'pl': 'Polish', - 'pt': 'Portuguese', - 'pa': 'Punjabi', - 'ro': 'Romanian', - 'ru': 'Russian', - 'sm': 'Samoan', - 'gd': 'Scots Gaelic', - 'sr': 'Serbian', - 'st': 'Sesotho', - 'sn': 'Shona', - 'sd': 'Sindhi', - 'si': 'Sinhala', - 'sk': 'Slovak', - 'sl': 'Slovenian', - 'so': 'Somali', - 'es': 'Spanish', - 'su': 'Sundanese', - 'sw': 'Swahili', - 'sv': 'Swedish', - 'tg': 'Tajik', - 'ta': 'Tamil', - 'te': 'Telugu', - 'th': 'Thai', - 'tr': 'Turkish', - 'uk': 'Ukrainian', - 'ur': 'Urdu', - 'uz': 'Uzbek', - 'vi': 'Vietnamese', - 'cy': 'Welsh', - 'xh': 'Xhosa', - 'yi': 'Yiddish', - 'yo': 'Yoruba', - 'zu': 'Zulu' +const languages = { + "auto": "Automatic", + "af": "Afrikaans", + "sq": "Albanian", + "am": "Amharic", + "ar": "Arabic", + "hy": "Armenian", + "az": "Azerbaijani", + "eu": "Basque", + "be": "Belarusian", + "bn": "Bengali", + "bs": "Bosnian", + "bg": "Bulgarian", + "ca": "Catalan", + "ceb": "Cebuano", + "ny": "Chichewa", + "zh-cn": "Chinese Simplified", + "zh-tw": "Chinese Traditional", + "co": "Corsican", + "hr": "Croatian", + "cs": "Czech", + "da": "Danish", + "nl": "Dutch", + "en": "English", + "eo": "Esperanto", + "et": "Estonian", + "tl": "Filipino", + "fi": "Finnish", + "fr": "French", + "fy": "Frisian", + "gl": "Galician", + "ka": "Georgian", + "de": "German", + "el": "Greek", + "gu": "Gujarati", + "ht": "Haitian Creole", + "ha": "Hausa", + "haw": "Hawaiian", + "iw": "Hebrew", + "hi": "Hindi", + "hmn": "Hmong", + "hu": "Hungarian", + "is": "Icelandic", + "ig": "Igbo", + "id": "Indonesian", + "ga": "Irish", + "it": "Italian", + "ja": "Japanese", + "jw": "Javanese", + "kn": "Kannada", + "kk": "Kazakh", + "km": "Khmer", + "ko": "Korean", + "ku": "Kurdish (Kurmanji)", + "ky": "Kyrgyz", + "lo": "Lao", + "la": "Latin", + "lv": "Latvian", + "lt": "Lithuanian", + "lb": "Luxembourgish", + "mk": "Macedonian", + "mg": "Malagasy", + "ms": "Malay", + "ml": "Malayalam", + "mt": "Maltese", + "mi": "Maori", + "mr": "Marathi", + "mn": "Mongolian", + "my": "Myanmar (Burmese)", + "ne": "Nepali", + "no": "Norwegian", + "ps": "Pashto", + "fa": "Persian", + "pl": "Polish", + "pt": "Portuguese", + "pa": "Punjabi", + "ro": "Romanian", + "ru": "Russian", + "sm": "Samoan", + "gd": "Scots Gaelic", + "sr": "Serbian", + "st": "Sesotho", + "sn": "Shona", + "sd": "Sindhi", + "si": "Sinhala", + "sk": "Slovak", + "sl": "Slovenian", + "so": "Somali", + "es": "Spanish", + "su": "Sundanese", + "sw": "Swahili", + "sv": "Swedish", + "tg": "Tajik", + "ta": "Tamil", + "te": "Telugu", + "th": "Thai", + "tr": "Turkish", + "uk": "Ukrainian", + "ur": "Urdu", + "uz": "Uzbek", + "vi": "Vietnamese", + "cy": "Welsh", + "xh": "Xhosa", + "yi": "Yiddish", + "yo": "Yoruba", + "zu": "Zulu" }; /** @@ -122,17 +123,17 @@ let languages = { * language is not supported */ function getISOCode(language) { - if (!language) return false; - language = language.toLowerCase(); - if (language in languages) return language; + if (!language) return false; + language = language.toLowerCase(); + if (language in languages) return language; - let keys = Object.keys(languages).filter((key) => { - if (typeof languages[key] !== 'string') return false; + let keys = Object.keys(languages).filter((key) => { + if (typeof languages[key] !== "string") return false; - return languages[key].toLowerCase() === language; - }); + return languages[key].toLowerCase() === language; + }); - return keys[0] || null; + return keys[0] || null; } /** @@ -141,7 +142,7 @@ function getISOCode(language) { * @returns {boolean} If the language is supported or not. */ function isSupported(language) { - return Boolean(getISOCode(language)); + return Boolean(getISOCode(language)); } module.exports = languages; diff --git a/src/tokenGenerator.js b/src/tokenGenerator.js index 16c41dd..1ae97e2 100644 --- a/src/tokenGenerator.js +++ b/src/tokenGenerator.js @@ -5,55 +5,55 @@ * Everything between 'BEGIN' and 'END' was copied from the script above. */ -const got = require('got'); +const got = require("got"); /* eslint-disable */ // BEGIN function zr(a) { - let b; - if (null !== yr) b = yr; - else { - b = wr(String.fromCharCode(84)); - let c = wr(String.fromCharCode(75)); - b = [ b(), b() ]; - b[1] = c(); - b = (yr = window[b.join(c())] || '') || ''; - } - let d = wr(String.fromCharCode(116)); - let c = wr(String.fromCharCode(107)); - d = [ d(), d() ]; - d[1] = c(); - c = '&' + d.join('') + '='; - d = b.split('.'); - b = Number(d[0]) || 0; - // eslint-disable-next-line no-var - for (var e = [], f = 0, g = 0; g < a.length; g++) { - let l = a.charCodeAt(g); - 128 > l ? e[f++] = l : (2048 > l ? e[f++] = l >> 6 | 192 : ((l & 64512) == 55296 && g + 1 < a.length && (a.charCodeAt(g + 1) & 64512) == 56320 ? (l = 65536 + ((l & 1023) << 10) + (a.charCodeAt(++g) & 1023), e[f++] = l >> 18 | 240, e[f++] = l >> 12 & 63 | 128) : e[f++] = l >> 12 | 224, e[f++] = l >> 6 & 63 | 128), e[f++] = l & 63 | 128); - } - a = b; - for (let f = 0; f < e.length; f++) a += e[f], a = xr(a, '+-a^+6'); - a = xr(a, '+-3^+b+-f'); - a ^= Number(d[1]) || 0; - 0 > a && (a = (a & 2147483647) + 2147483648); - a %= 1E6; - return c + (a.toString() + '.' + (a ^ b)); + let b; + if (null !== yr) b = yr; + else { + b = wr(String.fromCharCode(84)); + let c = wr(String.fromCharCode(75)); + b = [ b(), b() ]; + b[1] = c(); + b = (yr = window[b.join(c())] || "") || ""; + } + let d = wr(String.fromCharCode(116)); + let c = wr(String.fromCharCode(107)); + d = [ d(), d() ]; + d[1] = c(); + c = "&" + d.join("") + "="; + d = b.split("."); + b = Number(d[0]) || 0; + // eslint-disable-next-line no-var + for (var e = [], f = 0, g = 0; g < a.length; g++) { + let l = a.charCodeAt(g); + 128 > l ? e[f++] = l : (2048 > l ? e[f++] = l >> 6 | 192 : ((l & 64512) == 55296 && g + 1 < a.length && (a.charCodeAt(g + 1) & 64512) == 56320 ? (l = 65536 + ((l & 1023) << 10) + (a.charCodeAt(++g) & 1023), e[f++] = l >> 18 | 240, e[f++] = l >> 12 & 63 | 128) : e[f++] = l >> 12 | 224, e[f++] = l >> 6 & 63 | 128), e[f++] = l & 63 | 128); + } + a = b; + for (let f = 0; f < e.length; f++) a += e[f], a = xr(a, "+-a^+6"); + a = xr(a, "+-3^+b+-f"); + a ^= Number(d[1]) || 0; + 0 > a && (a = (a & 2147483647) + 2147483648); + a %= 1E6; + return c + (a.toString() + "." + (a ^ b)); } let yr = null; let wr = function(a) { - return function() { - return a; - }; + return function() { + return a; + }; }; let xr = function(a, b) { - for (let c = 0; c < b.length - 2; c += 3) { - let d = b.charAt(c + 2); - d = d >= 'a' ? d.charCodeAt(0) - 87 : Number(d); - d = b.charAt(c + 1) == '+' ? a >>> d : a << d; - a = b.charAt(c) == '+' ? a + d & 4294967295 : a ^ d; - } - return a; + for (let c = 0; c < b.length - 2; c += 3) { + let d = b.charAt(c + 2); + d = d >= "a" ? d.charCodeAt(0) - 87 : Number(d); + d = b.charAt(c + 1) == "+" ? a >>> d : a << d; + a = b.charAt(c) == "+" ? a + d & 4294967295 : a ^ d; + } + return a; }; // END /* eslint-enable */ @@ -61,60 +61,53 @@ let xr = function(a, b) { const config = new Map(); const window = { - TKK: config.get('TKK') || '0' + TKK: config.get("TKK") || "0" }; // eslint-disable-next-line require-jsdoc -function updateTKK() { - return new Promise(async (resolve, reject) => { +async function updateTKK() { try { - let now = Math.floor(Date.now() / 3600000); + let now = Math.floor(Date.now() / 3600000); - if (Number(window.TKK.split('.')[0]) === now) { - resolve(); - } - else { - let res = await got('https://translate.google.com'); + if (Number(window.TKK.split(".")[0]) !== now) { + let res = await got("https://translate.google.com"); - const code = res.body.match(/tkk:'\d+.\d+'/g); - // code will extract something like tkk:'1232135.131231321312', we need only value + // code will extract something like tkk:'1232135.131231321312', we need only value + const code = res.body.match(/tkk:'\d+.\d+'/g); - if (code.length > 0) { - // extracting value tkk:'1232135.131231321312', this will extract only token: 1232135.131231321312 - const xt = code[0].split(':')[1].replace(/'/g, ''); + if (code.length > 0) { + // extracting value tkk:'1232135.131231321312', this will extract only token: 1232135.131231321312 + const xt = code[0].split(":")[1].replace(/'/g, ""); - window.TKK = xt; - config.set('TKK', xt); + window.TKK = xt; + config.set("TKK", xt); + } } - - resolve(); - } } catch (e) { - if (e.name === 'HTTPError') { - let error = new Error(); - error.name = e.name; - error.statusCode = e.statusCode; - error.statusMessage = e.statusMessage; - reject(error); - } - reject(e); + if (e.name === "HTTPError") { + let error = new Error(); + error.name = e.name; + error.statusCode = e.statusCode; + error.statusMessage = e.statusMessage; + throw error; + } + throw e; } - }); } // eslint-disable-next-line require-jsdoc async function generate(text) { - try { - await updateTKK(); + try { + await updateTKK(); - let tk = zr(text); - tk = tk.replace('&tk=', ''); - return { name: 'tk', value: tk }; - } - catch (error) { - return error; - } + let tk = zr(text); + tk = tk.replace("&tk=", ""); + return { name: "tk", value: tk }; + } + catch (error) { + return error; + } } module.exports.generate = generate;