diff --git a/package.json b/package.json index 9616e440..d329db8c 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ } }, "dependencies": { + "axios": "^1.6.2", "concurrently": "^8.2.2", "husky": "^8.0.3", "lint-staged": "^15.1.0" diff --git a/server/api/controllers/cards/create.js b/server/api/controllers/cards/create.js index ab0c444e..ead92758 100755 --- a/server/api/controllers/cards/create.js +++ b/server/api/controllers/cards/create.js @@ -1,4 +1,5 @@ const moment = require('moment'); +const services = require('../../services/custom'); const Errors = { NOT_ENOUGH_RIGHTS: { @@ -108,6 +109,12 @@ module.exports = { }) .intercept('positionMustBeInValues', () => Errors.POSITION_MUST_BE_PRESENT); + const cardUrl = services.buildCardUrl(card); + const messageText = cardUrl + ' was created by ' + currentUser.username + ' in *' + list.name + '*'; + services.sendSlackMessage(messageText) + .then(() => { console.log('Slack message sent successfully.'); }) + .catch((error) => { console.error('Failed to send Slack message:', error.message); }); + return { item: card, }; diff --git a/server/api/controllers/cards/delete.js b/server/api/controllers/cards/delete.js index e2b6d00b..865cd2e9 100755 --- a/server/api/controllers/cards/delete.js +++ b/server/api/controllers/cards/delete.js @@ -1,3 +1,5 @@ +const services = require('../../services/custom'); + const Errors = { NOT_ENOUGH_RIGHTS: { notEnoughRights: 'Not enough rights', @@ -54,6 +56,11 @@ module.exports = { throw Errors.CARD_NOT_FOUND; } + const messageText = '*' + card.name + '* was deleted by ' + currentUser.username; + services.sendSlackMessage(messageText) + .then(() => { console.log('Slack message sent successfully.'); }) + .catch((error) => { console.error('Failed to send Slack message:', error.message); }); + return { item: card, }; diff --git a/server/api/controllers/cards/update.js b/server/api/controllers/cards/update.js index 8ee37523..df69f578 100755 --- a/server/api/controllers/cards/update.js +++ b/server/api/controllers/cards/update.js @@ -1,4 +1,5 @@ const moment = require('moment'); +const services = require('../../services/custom'); const Errors = { NOT_ENOUGH_RIGHTS: { @@ -175,6 +176,8 @@ module.exports = { 'isSubscribed', ]); + const cardPositionBefore = card.position; + card = await sails.helpers.cards.updateOne .with({ board, @@ -195,6 +198,17 @@ module.exports = { throw Errors.CARD_NOT_FOUND; } + const cardPositionAfter = card.position; + const cardMoved = cardPositionBefore !== cardPositionAfter; + + if (cardMoved) { + const cardUrl = services.buildCardUrl(card); + const messageText = cardUrl + ' was moved by ' + currentUser.username + ' to *' + nextList.name + '*'; + services.sendSlackMessage(messageText) + .then(() => { console.log('Slack message sent successfully.'); }) + .catch((error) => { console.error('Failed to send Slack message:', error.message); }); + } + return { item: card, }; diff --git a/server/api/controllers/comment-actions/create.js b/server/api/controllers/comment-actions/create.js index ddf4b991..7e5d97e8 100755 --- a/server/api/controllers/comment-actions/create.js +++ b/server/api/controllers/comment-actions/create.js @@ -1,3 +1,5 @@ +const services = require('../../services/custom'); + const Errors = { NOT_ENOUGH_RIGHTS: { notEnoughRights: 'Not enough rights', @@ -63,6 +65,12 @@ module.exports = { request: this.req, }); + const cardUrl = services.buildCardUrl(card); + const messageText = '*' + currentUser.username + '* commented on ' + cardUrl + ':\n>' + inputs.text; + services.sendSlackMessage(messageText) + .then(() => { console.log('Slack message sent successfully.'); }) + .catch((error) => { console.error('Failed to send Slack message:', error.message); }); + return { item: action, }; diff --git a/server/api/services/custom.js b/server/api/services/custom.js new file mode 100644 index 00000000..1166934a --- /dev/null +++ b/server/api/services/custom.js @@ -0,0 +1,73 @@ +const axios = require('axios'); +const slackPostUrl = 'https://slack.com/api/chat.postMessage'; +const channelId = 'C06B6F4R9RT'; + +const plankaProdUrl = 'https://kanban.glitchsecure.com'; +const plankaTestUrl = 'http://localhost:3000'; +const plankaTestWebhookUrl = 'https://hooks.slack.com/services/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'; +const slackAPIToken = process.env.SLACK_BOT_TOKEN; + +async function sendSlackMessage(messageText) { + if (!slackAPIToken) { + throw new Error('No Slack BOT token found'); + } + + console.log('Sending to Slack'); + + + const postData = { + blocks: [ { + type: 'section', + text: { + type: 'mrkdwn', + text: messageText, + }, + }] + }; + + try { + // Prod path + const config = { + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${slackAPIToken}`, + }, + }; + + axios.post(slackPostUrl, { ...postData, channel: channelId }, config) + .then(response => { + console.log('Slack response:', response.data); + }) + .catch(error => { + console.error('Error sending to Slack:', error.message); + }); + + + // Testing in dev environment (Brad) + /* + const response = await axios.post(plankaTestWebhookUrl, postData, { + headers: { + 'Content-Type': 'application/json' + } + }); + */ + + console.log('Slack response:', response.data); + return response.data; + } catch (error) { + console.error('Error sending to Slack:', error.message); + throw error; + } + } + + function buildCardUrl(card) { + const url = plankaProdUrl + '/cards/' + card.id; + const cardUrl = '<' + url + '|' + card.name + '>'; + console.log(cardUrl); + return cardUrl; + } + + module.exports = { + sendSlackMessage, + buildCardUrl + };