diff --git a/commands/interaction/slash/utils/translate.js b/commands/interaction/slash/utils/translate.js new file mode 100644 index 0000000..fe133c9 --- /dev/null +++ b/commands/interaction/slash/utils/translate.js @@ -0,0 +1,91 @@ +const { googleTranslate } = require('#api'); +const { TRANSLATE_LANGUAGES, TRANSLATE_DISPLAY_MAPPINGS } = require('#constants'); + +const { createEmbed } = require('#utils/embed') +const { codeblock, icon, pill, stringwrap } = require('#utils/markdown'); +const { editOrReply } = require('#utils/message') +const { STATICS } = require('#utils/statics'); +const { isSupported, getCodeFromAny } = require('#utils/translate'); + +const { translateLanguage } = require('#parameters').autocomplete; + +const { ApplicationCommandOptionTypes } = require('detritus-client/lib/constants'); +const { acknowledge } = require('#utils/interactions'); + +module.exports = { + name: 'translate', + description: 'Translate text from and to other languages.', + contexts: [ + 0, + 1, + 2 + ], + integrationTypes: [ + 1 + ], + options: [ + { + name: 'text', + description: 'Text to be translated.', + type: ApplicationCommandOptionTypes.TEXT, + required: true + }, + { + name: 'from', + description: 'Source Language.', + onAutoComplete: translateLanguage, + required: false + }, + { + name: 'to', + description: 'Target Language.', + onAutoComplete: translateLanguage, + required: false + }, + { + name: 'incognito', + description: 'Makes the response only visible to you.', + type: ApplicationCommandOptionTypes.BOOLEAN, + required: false, + default: false + } + ], + run: async (context, args) => { + await acknowledge(context, args.incognito); + + if(!args.to) args.to = "en"; + if(!args.from) args.from = "auto"; + + let content = args.text; + + if(!content.length) return editOrReply(context, createEmbed("warning", context, "No text supplied.")) + + if(!isSupported(args.to)) return editOrReply(context, createEmbed("warning", context, `Invalid target language (${stringwrap(args.to, 10, false)}).`)) + if(!isSupported(args.from)) return editOrReply(context, createEmbed("warning", context, `Invalid source language (${stringwrap(args.from, 10, false)}).`)) + + let targetLanguage = getCodeFromAny(args.to) + let sourceLanguage = getCodeFromAny(args.from) + + if(!targetLanguage) return editOrReply(context, createEmbed("warning", context, `Invalid target language (${stringwrap(args.to, 10, false)}).`)) + if(!sourceLanguage) return editOrReply(context, createEmbed("warning", context, `Invalid source language (${stringwrap(args.from, 10, false)}).`)) + + try{ + let translate = await googleTranslate(context, content, targetLanguage, sourceLanguage) + + let fromFlag = TRANSLATE_DISPLAY_MAPPINGS[translate.response.body.language.from || sourceLanguage] || '' + let toFlag = TRANSLATE_DISPLAY_MAPPINGS[translate.response.body.language.to] || '' + + return editOrReply(context, createEmbed("default", context, { + description: `${icon("locale")} ​ ${fromFlag} ${pill(TRANSLATE_LANGUAGES[translate.response.body.language.from || sourceLanguage] || translate.response.body.language.from || args.from)} ​ ​ ​​${icon("arrow_right")} ​ ​ ​ ​${toFlag} ${pill(TRANSLATE_LANGUAGES[translate.response.body.language.to] || translate.response.body.language.to)}\n${codeblock("ansi", [translate.response.body.translation])}`, + footer: { + iconUrl: STATICS.googletranslate, + text: `Google Translate • ${context.application.name}` + } + })) + }catch(e){ + if(e.response?.body?.status && e.response.body.status == 2) return editOrReply(context, createEmbed("error", context, `Unable to translate text.`)) + console.log(e) + return editOrReply(context, createEmbed("error", context, `Something went wrong.`)) + } + } +}; \ No newline at end of file diff --git a/commands/message/utils/translate.js b/commands/message/utils/translate.js index 9264f56..2330486 100644 --- a/commands/message/utils/translate.js +++ b/commands/message/utils/translate.js @@ -64,8 +64,8 @@ module.exports = { return editOrReply(context, createEmbed("default", context, { description: `${icon("locale")} ​ ${fromFlag} ${pill(TRANSLATE_LANGUAGES[translate.response.body.language.from || sourceLanguage] || translate.response.body.language.from || args.from)} ​ ​ ​​${icon("arrow_right")} ​ ​ ​ ​${toFlag} ${pill(TRANSLATE_LANGUAGES[translate.response.body.language.to] || translate.response.body.language.to)}\n${codeblock("ansi", [translate.response.body.translation])}`, footer: { - iconUrl: STATICS.google, - text: `Google Translator • ${context.application.name}` + iconUrl: STATICS.googletranslate, + text: `Google Translate • ${context.application.name}` } })) }catch(e){ diff --git a/labscore/parameters/autocomplete/translateLanguage.js b/labscore/parameters/autocomplete/translateLanguage.js new file mode 100644 index 0000000..251013d --- /dev/null +++ b/labscore/parameters/autocomplete/translateLanguage.js @@ -0,0 +1,35 @@ +const { TRANSLATE_LANGUAGES } = require("#constants"); +const { getLanguagesFromAny } = require("#utils/translate"); + +module.exports = async (context)=>{ + let choices = []; + if(context.value){ + choices = getLanguagesFromAny(context.value) + } else { + // Default language suggestions + choices = [ + "en", + "de", + "fr", + "es", + "pt-PT", + "no", + "fi", + "sv", + "it", + "ja", + "ru", + "ar", + "he", + "tr", + "hi", + "zh-CN", + "zh-TW", + ] + } + + return context.respond({ choices: choices.splice(0, 20).map((l)=>({ + name: TRANSLATE_LANGUAGES[l], + value: l + }))}); +} \ No newline at end of file diff --git a/labscore/parameters/index.js b/labscore/parameters/index.js new file mode 100644 index 0000000..3d04cfb --- /dev/null +++ b/labscore/parameters/index.js @@ -0,0 +1,5 @@ +module.exports = { + autocomplete: { + translateLanguage: require('./autocomplete/translateLanguage') + } +} \ No newline at end of file diff --git a/labscore/utils/statics.js b/labscore/utils/statics.js index e678775..7f23236 100644 --- a/labscore/utils/statics.js +++ b/labscore/utils/statics.js @@ -62,6 +62,10 @@ const Statics = Object.freeze({ file: "brands/googlefinance.png", revision: 0 }, + googletranslate: { + file: "brands/googletranslate.png", + revision: 0 + }, inferkit: { file: "brands/inferkit.png", revision: 1 @@ -212,6 +216,7 @@ module.exports.STATICS = Object.freeze({ genius: staticAsset(Statics.brands.genius), google: staticAsset(Statics.brands.google), googlefinance: staticAsset(Statics.brands.googlefinance), + googletranslate: staticAsset(Statics.brands.googletranslate), emojipedia: staticAsset(Statics.brands.emojipedia), inferkit: staticAsset(Statics.brands.inferkit), inspirobot: staticAsset(Statics.brands.inspirobot), diff --git a/labscore/utils/translate.js b/labscore/utils/translate.js index a4efdf7..3d77bd7 100644 --- a/labscore/utils/translate.js +++ b/labscore/utils/translate.js @@ -50,6 +50,14 @@ module.exports.dictionaryGetCodeFromAny = function (prompt) { return languages[0]; }; +module.exports.getLanguagesFromAny = function (prompt) { + let languages = []; + if(TRANSLATE_LANGUAGE_ALIASES[prompt.toLowerCase()]) prompt = TRANSLATE_LANGUAGE_ALIASES[prompt.toLowerCase()] + if(TRANSLATE_LANGUAGES[prompt.toLowerCase()]) languages.push(prompt.toLowerCase()); + for(const i of Object.keys(TRANSLATE_LANGUAGES)) if(!languages.includes(i) && (TRANSLATE_LANGUAGES[i].toLowerCase() == prompt.toLowerCase() || TRANSLATE_LANGUAGES[i].toLowerCase().includes(prompt.toLowerCase()))) languages.push(i) + for(const i of Object.keys(TRANSLATE_LANGUAGE_MAPPINGS)) if(!languages.includes(i) && TRANSLATE_LANGUAGE_MAPPINGS[i].toLowerCase() == prompt.toLowerCase()) languages.push(i) + return languages; +}; module.exports.isSupported = function (desiredLang) { return Boolean(getCode(desiredLang)); diff --git a/package.json b/package.json index 7f609a8..16046c5 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "#constants": "./labscore/constants.js", "#logging": "./labscore/logging.js", "#obelisk": "./labscore/api/obelisk/index.js", + "#parameters": "./labscore/parameters/index.js", "#permissions": "./labscore/permissions.js", "#utils/*": "./labscore/utils/*.js" }