Created
September 24, 2021 14:04
-
-
Save icebeat/fc179a1f4a4fedfd22420857cfaaeb61 to your computer and use it in GitHub Desktop.
JS function for sending Slack messages from Figma Hooks API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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