Skip to content

Instantly share code, notes, and snippets.

@guillegette
Last active May 7, 2017 12:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save guillegette/0acfbde6dad95d4882d4039a7abb04d4 to your computer and use it in GitHub Desktop.
Save guillegette/0acfbde6dad95d4882d4039a7abb04d4 to your computer and use it in GitHub Desktop.
Parse dates in natural language for Slack Message Menus
/* 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