const axios = require('axios') const decode = require('decode-html') const CHANNEL = '#dev' const ISSUE_REPO = 'foo/bar' exports.otochan = (req, res) => { console.log('Received request:', req.body) // slack challenge if (req.body.challenge) { res.send(req.body.challenge) return } // slack event if (req.body.event) { handleSlack(req, res) return } } function handleSlack(req, res) { const event = req.body.event if (event.type === 'reaction_added') { if (event.reaction === 'イシュー') { handleReaction(event) .then(() => { res.send('ok') }) .catch(err => { console.error(err) res.status(500).send(err.message) }) return } } res.send('ok: no matched handler') } async function handleReaction(event) { const { channel, ts } = event.item const { messages } = await getMessages(channel, ts, 10) const message = messages[0] const permalink = await getPermalink(channel, message.ts) const repo = ISSUE_REPO const title = decode(message.text) const historyText = messages.reverse() .filter(m => m.type === 'message') .map(m => decode(m.text)) .join("\n") const body = `${permalink}\n` + '```\n' + historyText + '\n```' const issues = await getLatestIssues(repo) const foundIssue = issues.find((issue) => { return issue.title === title }) if (foundIssue) { return } const issue = await createIssue(repo, { title: title, body: body }) const slackMessage = `<@${event.user}> ${issue.html_url}` await postMessage(channel, slackMessage) } function apiHeaders(token) { return { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` } } async function getMessages (channel, ts, count = 1) { const token = process.env.SLACK_USER_TOKEN const res = await axios.get('https://slack.com/api/channels.history', { params: { channel: channel, latest: ts, count: count, inclusive: true, token: token } }) return res.data } async function postMessage (channel, text) { const token = process.env.SLACK_TOKEN await axios.post('https://slack.com/api/chat.postMessage', { channel: channel, text: text, icon_emoji: ':chicken:' }, { headers: apiHeaders(token) }) } async function getPermalink (channel, ts) { const res = await axios.get('https://slack.com/api/chat.getPermalink', { params: { channel: channel, message_ts: ts, token: process.env.SLACK_TOKEN } }) return res.data.permalink } function githubApiHeaders() { return { ...apiHeaders(process.env.GITHUB_TOKEN), 'Accept': 'application/vnd.github.v3+json' } } async function createIssue(repo, params) { const res = await axios.post(`https://api.github.com/repos/${repo}/issues`, params, { headers: githubApiHeaders() }) if (res.status > 300) { console.error(res.data) throw new Error(res.data.message) } return res.data } async function getLatestIssues(repo) { const res = await axios.get(`https://api.github.com/repos/${repo}/issues`, { params: { state: 'all' }, headers: githubApiHeaders() }) if (res.status > 300) { console.error(res.data) throw new Error(res.data.message) } return res.data }