From d05c60d470b2bc843f85cb8312a60d54ac871cb7 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 7 Sep 2021 13:58:53 +0100 Subject: [PATCH] Adding slack integration. --- packages/auth/src/db/utils.js | 16 +++-- .../server/src/api/controllers/automation.js | 2 + packages/server/src/automations/actions.js | 4 +- .../server/src/automations/steps/discord.js | 22 +++++-- .../server/src/automations/steps/slack.js | 59 +++++++++++++++++++ packages/server/src/automations/triggers.js | 6 ++ packages/server/src/db/utils.js | 4 ++ 7 files changed, 102 insertions(+), 11 deletions(-) create mode 100644 packages/server/src/automations/steps/slack.js diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index 4cd29c9bc8..1116c0a605 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -35,10 +35,6 @@ exports.APP_PREFIX = DocumentTypes.APP + SEPARATOR exports.APP_DEV = exports.APP_DEV_PREFIX = DocumentTypes.APP_DEV + SEPARATOR exports.SEPARATOR = SEPARATOR -function isDevApp(app) { - return app.appId.startsWith(exports.APP_DEV_PREFIX) -} - /** * If creating DB allDocs/query params with only a single top level ID this can be used, this * is usually the case as most of our docs are top level e.g. tables, automations, users and so on. @@ -62,6 +58,18 @@ function getDocParams(docType, docId = null, otherProps = {}) { } } +exports.isDevAppID = appId => { + return appId.startsWith(exports.APP_DEV_PREFIX) +} + +exports.isProdAppID = appId => { + return appId.startsWith(exports.APP_PREFIX) && !exports.isDevAppID(appId) +} + +function isDevApp(app) { + return exports.isDevAppID(app.appId) +} + /** * Generates a new workspace ID. * @returns {string} The new workspace ID which the workspace doc can be stored under. diff --git a/packages/server/src/api/controllers/automation.js b/packages/server/src/api/controllers/automation.js index 8a3bbd93ec..40006b6865 100644 --- a/packages/server/src/api/controllers/automation.js +++ b/packages/server/src/api/controllers/automation.js @@ -280,3 +280,5 @@ exports.trigger = async function (ctx) { automation, } } + +exports.test = async function (ctx) {} diff --git a/packages/server/src/automations/actions.js b/packages/server/src/automations/actions.js index 767f1120d4..8d5d1693f1 100644 --- a/packages/server/src/automations/actions.js +++ b/packages/server/src/automations/actions.js @@ -9,7 +9,7 @@ const executeQuery = require("./steps/executeQuery") const outgoingWebhook = require("./steps/outgoingWebhook") const serverLog = require("./steps/serverLog") const discord = require("./steps/discord") -// TODO: remove zapier/integromat some time in the future/deprecate them +const slack = require("./steps/slack") const zapier = require("./steps/zapier") const integromat = require("./steps/integromat") @@ -26,6 +26,7 @@ const ACTION_IMPLS = { SERVER_LOG: serverLog.run, // these used to be lowercase step IDs, maintain for backwards compat discord: discord.run, + slack: slack.run, zapier: zapier.run, integromat: integromat.run, } @@ -42,6 +43,7 @@ const ACTION_DEFINITIONS = { SERVER_LOG: serverLog.definition, // these used to be lowercase step IDs, maintain for backwards compat discord: discord.definition, + slack: slack.definition, zapier: zapier.definition, integromat: integromat.definition, } diff --git a/packages/server/src/automations/steps/discord.js b/packages/server/src/automations/steps/discord.js index 2fefc92916..c01619b0ae 100644 --- a/packages/server/src/automations/steps/discord.js +++ b/packages/server/src/automations/steps/discord.js @@ -1,5 +1,8 @@ const fetch = require("node-fetch") +const DEFAULT_USERNAME = "Budibase Automate" +const DEFAULT_AVATAR_URL = "https://i.imgur.com/a1cmTKM.png" + exports.definition = { name: "Discord Message", tagline: "Send a message to a Discord server", @@ -7,10 +10,7 @@ exports.definition = { icon: "ri-discord-line", stepId: "discord", type: "ACTION", - inputs: { - username: "Budibase Automate", - avatar_url: "https://i.imgur.com/a1cmTKM.png", - }, + inputs: {}, schema: { inputs: { properties: { @@ -39,14 +39,23 @@ exports.definition = { type: "number", description: "The HTTP status code of the request", }, + success: { + type: "boolean", + description: "Whether the message sent successfully", + }, }, }, }, } exports.run = async function ({ inputs }) { - const { url, username, avatar_url, content } = inputs - + let { url, username, avatar_url, content } = inputs + if (!username) { + username = DEFAULT_USERNAME + } + if (!avatar_url) { + avatar_url = DEFAULT_AVATAR_URL + } const response = await fetch(url, { method: "post", body: JSON.stringify({ @@ -61,5 +70,6 @@ exports.run = async function ({ inputs }) { return { httpStatus: response.status, + success: response.status === 200, } } diff --git a/packages/server/src/automations/steps/slack.js b/packages/server/src/automations/steps/slack.js new file mode 100644 index 0000000000..08c26fe6d3 --- /dev/null +++ b/packages/server/src/automations/steps/slack.js @@ -0,0 +1,59 @@ +const fetch = require("node-fetch") + +const DEFAULT_USERNAME = "Budibase Automate" +const DEFAULT_ICON_URL = "https://i.imgur.com/a1cmTKM.png" + +exports.definition = { + name: "Slack Message", + tagline: "Send a message to Slack", + description: "Send a message to Slack", + icon: "ri-slack-line", + stepId: "slack", + type: "ACTION", + inputs: {}, + schema: { + inputs: { + properties: { + url: { + type: "string", + title: "Incoming Webhook URL", + }, + text: { + type: "string", + title: "Message", + }, + }, + required: ["url", "text"], + }, + outputs: { + properties: { + httpStatus: { + type: "number", + description: "The HTTP status code of the request", + }, + success: { + type: "boolean", + description: "Whether the message sent successfully", + }, + }, + }, + }, +} + +exports.run = async function ({ inputs }) { + let { url, text } = inputs + const response = await fetch(url, { + method: "post", + body: JSON.stringify({ + text, + }), + headers: { + "Content-Type": "application/json", + }, + }) + + return { + httpStatus: response.status, + success: response.status === 200, + } +} diff --git a/packages/server/src/automations/triggers.js b/packages/server/src/automations/triggers.js index 3ce09e15fd..b76cd4ce2a 100644 --- a/packages/server/src/automations/triggers.js +++ b/packages/server/src/automations/triggers.js @@ -9,6 +9,7 @@ const { coerce } = require("../utilities/rowProcessor") const { utils } = require("@budibase/auth/redis") const { JobQueues } = require("../constants") const { definitions } = require("./triggerInfo") +const { isDevAppID } = require("../db/utils") const { opts } = utils.getRedisOptions() let automationQueue = new Queue(JobQueues.AUTOMATIONS, { redis: opts }) @@ -19,6 +20,11 @@ async function queueRelevantRowAutomations(event, eventType) { if (event.appId == null) { throw `No appId specified for ${eventType} - check event emitters.` } + // don't queue events which are for dev apps, only way to test automations is + // running tests on them + if (isDevAppID(event.appId)) { + return + } const db = new CouchDB(event.appId) let automations = await db.allDocs( getAutomationParams(null, { include_docs: true }) diff --git a/packages/server/src/db/utils.js b/packages/server/src/db/utils.js index 92734c5e7b..987e9f58f8 100644 --- a/packages/server/src/db/utils.js +++ b/packages/server/src/db/utils.js @@ -7,6 +7,8 @@ const { APP_PREFIX, SEPARATOR, StaticDatabases, + isDevAppID, + isProdAppID, } = require("@budibase/auth/db") const UNICODE_MAX = "\ufff0" @@ -62,6 +64,8 @@ const BudibaseInternalDB = { exports.APP_PREFIX = APP_PREFIX exports.APP_DEV_PREFIX = APP_DEV_PREFIX +exports.isDevAppID = isDevAppID +exports.isProdAppID = isProdAppID exports.USER_METDATA_PREFIX = `${DocumentTypes.ROW}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}` exports.LINK_USER_METADATA_PREFIX = `${DocumentTypes.LINK}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}` exports.ViewNames = ViewNames