You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
planka_custom/server/api/helpers/utils/send-message.js

176 lines
4.3 KiB
JavaScript

/**
* @description Create a default message for a given action
* @param {*} user
* @param {*} card
* @param {*} action
* @returns Markdown message or empty string if no action was found
*/
function buildMessage(user, card, action) {
const cardLink = `<${sails.config.custom.baseUrl}/cards/${card.id}|${card.name}>`;
let markdown;
switch (action.type) {
case Action.Types.CREATE_CARD:
markdown = `${cardLink} was created by ${user.name} in *${action.data.list.name}*`;
break;
case Action.Types.MOVE_CARD:
markdown = `${cardLink} was moved by ${user.name} to *${action.data.toList.name}*`;
break;
case Action.Types.COMMENT_CARD:
markdown = `*${user.name}* commented on ${cardLink}:\n>${action.data.text}`;
break;
case Action.Types.DELETE_COMMENT_CARD:
markdown = `Comment on ${cardLink} was deleted by ${user.name}`;
break;
case Action.Types.DELETE_CARD:
markdown = `${cardLink} was deleted by ${user.name}`;
break;
default:
return '';
}
return markdown;
}
/**
* @description Handle Slack messages, it checks if the necessary tokens are set as environment variables and sends the message
* @returns Object with send method
*/
const handleSlack = () => {
const POST_MESSAGE_API_URL = 'https://slack.com/api/chat.postMessage';
const TOKEN = sails.config.custom.slackBotToken;
const CHANNEL = sails.config.custom.slackChannelId;
const send = async ({ action, user, card }) => {
if (!TOKEN || !CHANNEL) {
return;
}
const markdown = buildMessage(user, card, action);
if (!markdown) {
sails.log.warn('Missing message markdown. Skipping Slack message. Action:', action.type);
return;
}
const data = {
channel: CHANNEL,
text: markdown,
as_user: false,
username: user.name,
icon_url: user.avatarUrl,
};
try {
const response = await fetch(POST_MESSAGE_API_URL, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: `Bearer ${TOKEN}`,
},
});
if (!response.ok) {
const errorData = await response.json();
sails.log.error('Failed to send Slack message:', errorData);
} else {
const responseJson = await response.json();
sails.log.debug('Slack message sent successfully:', responseJson);
}
} catch (error) {
sails.log.error('Error sending Slack message:', error);
}
};
return {
send,
};
};
/**
* @description Handle Webhook messages, it checks if a webhook url is given and sends the message. Optionally, it can include a bearer token, if set via environment variable.
* @returns Object with send method
*/
const handleWebhook = () => {
const URL = sails.config.custom.webhookUrl;
const TOKEN = sails.config.custom.webhookBearerToken;
function buildHeaders() {
const headers = {
'Content-Type': 'application/json',
};
if (TOKEN) {
headers.Authorization = `Bearer ${TOKEN}`;
}
return headers;
}
const send = async ({ action, user, card, board }) => {
if (!URL) {
return;
}
const markdown = buildMessage(user, card, action);
const data = {
text: markdown,
action,
board,
card,
user: _.pick(user, ['id', 'name', 'avatarUrl', 'email']),
};
try {
const response = await fetch(URL, {
method: 'POST',
headers: buildHeaders(),
body: JSON.stringify(data),
});
if (!response.ok) {
const errorData = await response.json();
sails.log.error('Failed to send Webhook message:', errorData);
} else {
sails.log.debug('Webhook message sent successfully.');
}
} catch (error) {
sails.log.error('Error sending Webhook message:', error);
}
};
return {
send,
};
};
module.exports = {
inputs: {
action: {
type: 'ref',
required: true,
},
user: {
type: 'ref',
required: true,
},
card: {
type: 'ref',
required: true,
},
board: {
type: 'ref',
required: true,
},
},
async fn(inputs) {
const slack = handleSlack();
const webhook = handleWebhook();
await Promise.allSettled([slack.send(inputs), webhook.send(inputs)]);
},
};