slack-bot.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. const express = require('express');
  2. const loggerFactory = require('@alias/logger');
  3. const logger = loggerFactory('growi:routes:apiv3:slack-bot');
  4. const router = express.Router();
  5. const { verificationSlackRequest } = require('@growi/slack');
  6. module.exports = (crowi) => {
  7. this.app = crowi.express;
  8. // Check if the access token is correct
  9. function verificationAccessToken(req, res, next) {
  10. const slackBotAccessToken = req.body.slack_bot_access_token || null;
  11. if (slackBotAccessToken == null || slackBotAccessToken !== this.crowi.configManager.getConfig('crowi', 'slackbot:access-token')) {
  12. logger.error('slack_bot_access_token is invalid.');
  13. return res.send('*Access token is inValid*');
  14. }
  15. return next();
  16. }
  17. function verificationRequestUrl(req, res, next) {
  18. // for verification request URL on Event Subscriptions
  19. if (req.body.type === 'url_verification') {
  20. return res.send(req.body);
  21. }
  22. return next();
  23. }
  24. const addSlackBotSigningSecret = (req, res, next) => {
  25. req.signingSecret = crowi.configManager.getConfig('crowi', 'slackbot:signingSecret');
  26. return next();
  27. };
  28. router.post('/commands', verificationRequestUrl, addSlackBotSigningSecret, verificationSlackRequest, verificationAccessToken, async(req, res) => {
  29. // Send response immediately to avoid opelation_timeout error
  30. // See https://api.slack.com/apis/connections/events-api#the-events-api__responding-to-events
  31. res.send();
  32. const { body } = req;
  33. const args = body.text.split(' ');
  34. const command = args[0];
  35. try {
  36. switch (command) {
  37. case 'search':
  38. await crowi.slackBotService.showEphemeralSearchResults(body, args);
  39. break;
  40. case 'create':
  41. await crowi.slackBotService.createModal(body);
  42. break;
  43. default:
  44. await crowi.slackBotService.notCommand(body);
  45. break;
  46. }
  47. }
  48. catch (error) {
  49. logger.error(error);
  50. return res.send(error.message);
  51. }
  52. });
  53. const handleBlockActions = async(payload) => {
  54. const { action_id: actionId } = payload.actions[0];
  55. switch (actionId) {
  56. case 'shareSearchResults': {
  57. await crowi.slackBotService.shareSearchResults(payload);
  58. break;
  59. }
  60. case 'showNextResults': {
  61. const parsedValue = JSON.parse(payload.actions[0].value);
  62. const { body, args, offset } = parsedValue;
  63. const newOffset = offset + 10;
  64. await crowi.slackBotService.showEphemeralSearchResults(body, args, newOffset);
  65. break;
  66. }
  67. default:
  68. break;
  69. }
  70. };
  71. const handleViewSubmission = async(payload) => {
  72. const { callback_id: callbackId } = payload.view;
  73. switch (callbackId) {
  74. case 'createPage':
  75. await crowi.slackBotService.createPageInGrowi(payload);
  76. break;
  77. default:
  78. break;
  79. }
  80. };
  81. router.post('/interactions', verificationRequestUrl, addSlackBotSigningSecret, verificationSlackRequest, async(req, res) => {
  82. // Send response immediately to avoid opelation_timeout error
  83. // See https://api.slack.com/apis/connections/events-api#the-events-api__responding-to-events
  84. res.send();
  85. const payload = JSON.parse(req.body.payload);
  86. const { type } = payload;
  87. try {
  88. switch (type) {
  89. case 'block_actions':
  90. await handleBlockActions(payload);
  91. break;
  92. case 'view_submission':
  93. await handleViewSubmission(payload);
  94. break;
  95. default:
  96. break;
  97. }
  98. }
  99. catch (error) {
  100. logger.error(error);
  101. return res.send(error.message);
  102. }
  103. });
  104. return router;
  105. };