Skip to content

Instantly share code, notes, and snippets.

@icebeat
Created September 24, 2021 14:04
Show Gist options
  • Save icebeat/fc179a1f4a4fedfd22420857cfaaeb61 to your computer and use it in GitHub Desktop.
Save icebeat/fc179a1f4a4fedfd22420857cfaaeb61 to your computer and use it in GitHub Desktop.
JS function for sending Slack messages from Figma Hooks API
const https = require('https');
const SLACK_TOKEN = '';
const PASSCODE = '';
const CHANNEL_REGEX = /\s(\#.*)$/;
const JIRA_REGEX = /^(JIRA-[^\s]+)\s/;
const DEFAULT_CHANNEL = '';
const TEAM_ID = '';
// FILE NAME: JIRA-1234 UI KIT #channel
// Send message to Slack
const postMessage = (data) => {
const payload = JSON.stringify(data);
const options = {
hostname: 'slack.com',
path: '/api/chat.postMessage',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': payload.length,
'Authorization': `Bearer ${SLACK_TOKEN}`
}
};
return new Promise((resolve, reject) => {
const request = https.request(options, res => {
// handle http errors
if (res.statusCode < 200 || res.statusCode > 299) {
reject(new Error('Failed to load page, status code: ' + res.statusCode));
}
// temporary data holder
const body = [];
// on every content chunk, push it to the data array
res.on('data', (chunk) => body.push(chunk));
// we are done, resolve promise with those joined chunks
res.on('end', () => resolve(JSON.parse(body.join(''))));
});
// handle connection errors of the request
request.on('error', (err) => reject(err));
request.write(payload);
request.end();
});
};
const getChannels = () => {
const options = {
hostname: 'slack.com',
path: '/api/conversations.list?exclude_archived=true&limit=300',
method: 'GET',
headers: {
'Authorization': `Bearer ${SLACK_TOKEN}`
}
};
return new Promise((resolve, reject) => {
const request = https.request(options, res => {
// handle http errors
if (res.statusCode < 200 || res.statusCode > 299) {
reject(new Error('Failed to load page, status code: ' + res.statusCode));
}
// temporary data holder
const body = [];
// on every content chunk, push it to the data array
res.on('data', (chunk) => body.push(chunk));
// we are done, resolve promise with those joined chunks
res.on('end', () => resolve(JSON.parse(body.join(''))));
});
// handle connection errors of the request
request.on('error', (err) => reject(err));
request.end();
});
};
module.exports = async (req, res) => {
// If valid figma endpoint?
if (!!req.body && req.body.passcode === PASSCODE) {
console.log(req.body)
let { event_type, file_name, file_key, triggered_by } = req.body;
// Has a custom channel?
let capture;
let channel_name;
let channel_id;
if (capture = CHANNEL_REGEX.exec(file_name)) {
let [all, channel] = capture;
file_name = file_name.slice(0, -all.length);
channel_name = channel.slice(1);
}
// Compose Blocks
let blocks = [];
// If new version?
if ( event_type === 'FILE_VERSION_UPDATE') {
let { label, description } = req.body;
blocks.push({
'type': 'section',
'text': {
'type': 'mrkdwn',
'text': `*${triggered_by.handle}* added a new version on *<https://www.figma.com/file/${file_key}|${file_name}>*`
}
},{
'type': 'section',
'text': {
'type': 'mrkdwn',
'text': `*${label}*\n${description}`
}
});
// Get channel ID
let data = await getChannels();
if (!!data && data.ok) {
let item = data.channels.find(channel => channel.name === channel_name);
if (item) {
channel_id = item.id;
}
}
}
// If new comment?
if ( event_type === 'FILE_COMMENT') {
let { comment, mentions } = req.body;
let text = [];
color = '#1ABCFE';
comment.map(item => {
if (!!item.mention) {
text.push(`@${mentions.filter(mention => (mention.id == item.mention))[0].handle}`);
} else if (!!item.text) {
text.push(item.text);
}
});
blocks.push({
'type': 'section',
'text': {
'type': 'mrkdwn',
'text': `*${triggered_by.handle}* left a comment on *<https://www.figma.com/file/${file_key}|${file_name}>*`
}
},{
'type': 'section',
'text': {
'type': 'mrkdwn',
'text': text.join('')
}
});
}
// Actions
let actions = [{
type: 'mrkdwn',
text: `Open in <https://www.figma.com/file/${file_key}|Figma>`
}];
// // Has a Jira issue?
let jira_issue;
if (jira_issue = JIRA_REGEX.exec(file_name)) {
actions.push({
type: 'mrkdwn',
text: `View <https://localistico.atlassian.net/browse/${jira_issue[1]}|Jira Issue>`
});
}
blocks.push({
'type': 'context',
'elements': actions
});
// Compose message
const data = {
channel: DEFAULT_CHANNEL,
unfurl_links: true,
blocks,
};
try {
// Send to default channel
if ( event_type === 'FILE_VERSION_UPDATE' || event_type === 'FILE_COMMENT') {
let body = await postMessage(data);
}
// Send to custom channel
if (channel_id) {
await postMessage({
...data,
channel: channel_id
});
}
} catch (error) {}
}
// Always send OK to avoid retries
res.status(200).send('OK');
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment