Last active
May 7, 2017 12:09
-
-
Save guillegette/0acfbde6dad95d4882d4039a7abb04d4 to your computer and use it in GitHub Desktop.
Parse dates in natural language for Slack Message Menus
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
/* Example payload | |
{ | |
name: 'set_due_date', | |
value: '', | |
callback_id: 'new_task_message', | |
team: { id: 'TXXXXXXXX', domain: 'gette' }, | |
channel: { id: 'CXXXXXXXX', name: 'work' }, | |
user: { id: 'UXXXXXXXX', name: 'guillegette' }, | |
action_ts: '1494154614.757129', | |
message_ts: '1494138801.457727', | |
attachment_id: '2', | |
token: '...' | |
} | |
*/ | |
const express = require('express'); | |
const router = express.Router(); | |
const chrono = require('chrono-node'); | |
const moment = require('moment-timezone'); | |
router.post('/options', (req, res, next) => { | |
if (req.body.name !== 'set_due_date') { | |
// You can only set 1 options API url in Slack, so you need to keep this in | |
// mind if you have multiple types of menus | |
return next('Not a valid call'); | |
} | |
const userInput = req.body.value; | |
// The user click for the firt time on the message menu and we are returning | |
// a default list of options. | |
if (!userInput) { | |
return res.json({options: [ | |
{value: 'tomorrow', text: 'Tomorrow'}, | |
{value: 'in 2 days', text: 'In 2 days'}, | |
{value: 'on monday', text: 'On Monday'}, | |
{value: 'next week', text: 'Next week'} | |
]}); | |
} | |
// Unfortunately, Slack does not provide the user timezone as part of the payload | |
// so hopefully you have this information in your database or you can get it | |
// using the users.info API endpoint | |
const userTimezone = getUserTimezone(req.body.user.id); | |
const userLocalTime = moment.tz(userTimezone).toDate(); | |
// chrono.parse('text to parse', 'offset'); | |
// offset is a Date object representing the user localtime, because tomorrow is not | |
// the same if the user is in Sydney or in San Francisco. | |
const dateResults = chrono.parse(userInput, userLocalTime); | |
if (dateResults.length === 0) { | |
return res.json({ | |
options: [] | |
}); | |
} | |
// We iterate over the parsed results and we use moment.js to turn the date object | |
// into a nice format https://momentjs.com/docs/#/displaying/ | |
const dueDates = dateResults.map((result) => { | |
const date = result.start.date(); | |
return { | |
value: date.toString(), | |
text: moment(date).format('ddd, hA') | |
} | |
}); | |
return res.json({ | |
options: dueDates | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment