From 527dfe697178f9e864344c5b4d28d9b1de154ba2 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Mon, 7 Nov 2022 18:28:20 +0100 Subject: [PATCH] feat: Add DeepL integration with translate text action --- .../backend/src/apps/deepl/actions/index.ts | 3 + .../deepl/actions/translate-text/index.ts | 77 +++++++++++++++++++ .../backend/src/apps/deepl/assets/favicon.svg | 39 ++++++++++ packages/backend/src/apps/deepl/auth/index.ts | 69 +++++++++++++++++ .../src/apps/deepl/auth/is-still-verified.ts | 13 ++++ .../src/apps/deepl/auth/verify-credentials.ts | 11 +++ .../src/apps/deepl/common/add-auth-header.ts | 12 +++ packages/backend/src/apps/deepl/index.d.ts | 0 packages/backend/src/apps/deepl/index.ts | 18 +++++ 9 files changed, 242 insertions(+) create mode 100644 packages/backend/src/apps/deepl/actions/index.ts create mode 100644 packages/backend/src/apps/deepl/actions/translate-text/index.ts create mode 100644 packages/backend/src/apps/deepl/assets/favicon.svg create mode 100644 packages/backend/src/apps/deepl/auth/index.ts create mode 100644 packages/backend/src/apps/deepl/auth/is-still-verified.ts create mode 100644 packages/backend/src/apps/deepl/auth/verify-credentials.ts create mode 100644 packages/backend/src/apps/deepl/common/add-auth-header.ts create mode 100644 packages/backend/src/apps/deepl/index.d.ts create mode 100644 packages/backend/src/apps/deepl/index.ts diff --git a/packages/backend/src/apps/deepl/actions/index.ts b/packages/backend/src/apps/deepl/actions/index.ts new file mode 100644 index 00000000..db83a4f4 --- /dev/null +++ b/packages/backend/src/apps/deepl/actions/index.ts @@ -0,0 +1,3 @@ +import translateText from './translate-text'; + +export default [translateText]; diff --git a/packages/backend/src/apps/deepl/actions/translate-text/index.ts b/packages/backend/src/apps/deepl/actions/translate-text/index.ts new file mode 100644 index 00000000..4b74a8ce --- /dev/null +++ b/packages/backend/src/apps/deepl/actions/translate-text/index.ts @@ -0,0 +1,77 @@ +import qs from 'qs'; +import defineAction from '../../../../helpers/define-action'; + +export default defineAction({ + name: 'Translate Text', + key: 'translateText', + description: 'Translates text from one language to another.', + arguments: [ + { + label: 'Text', + key: 'text', + type: 'string' as const, + required: true, + description: 'Text to be translated.', + variables: true, + }, + { + label: 'Target Language', + key: 'targetLanguage', + type: 'dropdown' as const, + required: true, + description: 'Language to translate the text to.', + variables: false, + value: '', + options: [ + { label: 'Bulgarian', value: 'BG' }, + { label: 'Chinese (simplified)', value: 'ZH' }, + { label: 'Czech', value: 'CS' }, + { label: 'Danish', value: 'DA' }, + { label: 'Dutch', value: 'NL' }, + { label: 'English', value: 'EN' }, + { label: 'English (American)', value: 'EN-US' }, + { label: 'English (British)', value: 'EN-GB' }, + { label: 'Estonian', value: 'ET' }, + { label: 'Finnish', value: 'FI' }, + { label: 'French', value: 'FR' }, + { label: 'German', value: 'DE' }, + { label: 'Greek', value: 'EL' }, + { label: 'Hungarian', value: 'HU' }, + { label: 'Indonesian', value: 'ID' }, + { label: 'Italian', value: 'IT' }, + { label: 'Japanese', value: 'JA' }, + { label: 'Latvian', value: 'LV' }, + { label: 'Lithuanian', value: 'LT' }, + { label: 'Polish', value: 'PL' }, + { label: 'Portuguese', value: 'PT' }, + { label: 'Portuguese (Brazilian)', value: 'PT-BR' }, + { + label: + 'Portuguese (all Portuguese varieties excluding Brazilian Portuguese)', + value: 'PT-PT', + }, + { label: 'Romanian', value: 'RO' }, + { label: 'Russian', value: 'RU' }, + { label: 'Slovak', value: 'SK' }, + { label: 'Slovenian', value: 'SL' }, + { label: 'Spanish', value: 'ES' }, + { label: 'Swedish', value: 'SV' }, + { label: 'Turkish', value: 'TR' }, + { label: 'Ukrainian', value: 'UK' }, + ], + }, + ], + + async run($) { + const stringifiedBody = qs.stringify({ + text: $.step.parameters.text, + target_lang: $.step.parameters.targetLanguage, + }); + + const response = await $.http.post('/v2/translate', stringifiedBody); + + $.setActionItem({ + raw: response.data, + }); + }, +}); diff --git a/packages/backend/src/apps/deepl/assets/favicon.svg b/packages/backend/src/apps/deepl/assets/favicon.svg new file mode 100644 index 00000000..7b96b43e --- /dev/null +++ b/packages/backend/src/apps/deepl/assets/favicon.svg @@ -0,0 +1,39 @@ + + image/svg+xml + + + + + + + background + + + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/backend/src/apps/deepl/auth/index.ts b/packages/backend/src/apps/deepl/auth/index.ts new file mode 100644 index 00000000..55576c98 --- /dev/null +++ b/packages/backend/src/apps/deepl/auth/index.ts @@ -0,0 +1,69 @@ +import verifyCredentials from './verify-credentials'; +import isStillVerified from './is-still-verified'; + +export default { + fields: [ + { + key: 'screenName', + label: 'Screen Name', + type: 'string' as const, + required: true, + readOnly: false, + value: null, + placeholder: null, + description: + 'Screen name of your connection to be used on Automatisch UI.', + clickToCopy: false, + }, + { + key: 'authenticationKey', + label: 'Authenticatin Key', + type: 'string' as const, + required: true, + readOnly: false, + value: null, + placeholder: null, + description: 'DeepL authentication key of your account.', + clickToCopy: false, + }, + ], + authenticationSteps: [ + { + type: 'mutation' as const, + name: 'createConnection', + arguments: [ + { + name: 'key', + value: '{key}', + }, + { + name: 'formattedData', + value: null, + properties: [ + { + name: 'screenName', + value: '{fields.screenName}', + }, + { + name: 'authenticationKey', + value: '{fields.authenticationKey}', + }, + ], + }, + ], + }, + { + type: 'mutation' as const, + name: 'verifyConnection', + arguments: [ + { + name: 'id', + value: '{createConnection.id}', + }, + ], + }, + ], + + verifyCredentials, + isStillVerified, +}; diff --git a/packages/backend/src/apps/deepl/auth/is-still-verified.ts b/packages/backend/src/apps/deepl/auth/is-still-verified.ts new file mode 100644 index 00000000..95a1ef29 --- /dev/null +++ b/packages/backend/src/apps/deepl/auth/is-still-verified.ts @@ -0,0 +1,13 @@ +import { IGlobalVariable } from '@automatisch/types'; +import verifyCredentials from './verify-credentials'; + +const isStillVerified = async ($: IGlobalVariable) => { + try { + await verifyCredentials($); + return true; + } catch (error) { + return false; + } +}; + +export default isStillVerified; diff --git a/packages/backend/src/apps/deepl/auth/verify-credentials.ts b/packages/backend/src/apps/deepl/auth/verify-credentials.ts new file mode 100644 index 00000000..18c184a3 --- /dev/null +++ b/packages/backend/src/apps/deepl/auth/verify-credentials.ts @@ -0,0 +1,11 @@ +import { IGlobalVariable } from '@automatisch/types'; + +const verifyCredentials = async ($: IGlobalVariable) => { + await $.http.get('/v2/usage'); + + await $.auth.set({ + screenName: $.auth.data.screenName, + }); +}; + +export default verifyCredentials; diff --git a/packages/backend/src/apps/deepl/common/add-auth-header.ts b/packages/backend/src/apps/deepl/common/add-auth-header.ts new file mode 100644 index 00000000..864970e5 --- /dev/null +++ b/packages/backend/src/apps/deepl/common/add-auth-header.ts @@ -0,0 +1,12 @@ +import { TBeforeRequest } from '@automatisch/types'; + +const addAuthHeader: TBeforeRequest = ($, requestConfig) => { + if ($.auth.data?.authenticationKey) { + const authorizationHeader = `DeepL-Auth-Key ${$.auth.data.authenticationKey}`; + requestConfig.headers.Authorization = authorizationHeader; + } + + return requestConfig; +}; + +export default addAuthHeader; diff --git a/packages/backend/src/apps/deepl/index.d.ts b/packages/backend/src/apps/deepl/index.d.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/backend/src/apps/deepl/index.ts b/packages/backend/src/apps/deepl/index.ts new file mode 100644 index 00000000..b77ea2d8 --- /dev/null +++ b/packages/backend/src/apps/deepl/index.ts @@ -0,0 +1,18 @@ +import defineApp from '../../helpers/define-app'; +import addAuthHeader from './common/add-auth-header'; +import auth from './auth'; +import actions from './actions'; + +export default defineApp({ + name: 'DeepL', + key: 'deepl', + iconUrl: '{BASE_URL}/apps/deepl/assets/favicon.svg', + authDocUrl: 'https://automatisch.io/docs/apps/deepl/connection', + supportsConnections: true, + baseUrl: 'https://deepl.com', + apiBaseUrl: 'https://api.deepl.com', + primaryColor: '0d2d45', + beforeRequest: [addAuthHeader], + auth, + actions, +});