UNPKG

botpress

Version:

The world's first CMS for bots. Easily create, manage and extend chatbots.

286 lines (240 loc) 9.19 kB
'use strict'; var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); var _nanoid = require('nanoid'); var _nanoid2 = _interopRequireDefault(_nanoid); var _helpers = require('./database/helpers'); var _helpers2 = _interopRequireDefault(_helpers); var _util = require('./util'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } const getOriginatingModule = () => { const origPrepareStackTrace = Error.prepareStackTrace; Error.prepareStackTrace = (_, stack) => stack; const err = new Error(); const stack = err.stack; Error.prepareStackTrace = origPrepareStackTrace; stack.shift(); return stack[1].getFileName(); }; const notifications = ({ knex, modules, logger, events }) => { const toDatabase = (knex, notification) => ({ id: notification.id, message: notification.message, level: notification.level, module_id: notification.moduleId, module_icon: notification.icon, module_name: notification.name, redirect_url: notification.url, created_on: (0, _helpers2.default)(knex).date.now(), read: (0, _helpers2.default)(knex).bool.false(), archived: (0, _helpers2.default)(knex).bool.false() }); const fromDatabase = (knex, row) => ({ id: row.id, message: row.message, level: row.level, moduleId: row.module_id, icon: row.module_icon, name: row.module_name, url: row.redirect_url, date: new Date(row.created_on), sound: false, read: (0, _helpers2.default)(knex).bool.parse(row.read) }); // TODO: a bunch of functions below doesn't use `await`, should they actually be `async`? /** * Marks a single notification as read (but doesn't archive it) * @param {string} notificationId The id of the notification to mark as read * @return {Promise} */ const markAsRead = (() => { var _ref = _asyncToGenerator(function* (notificationId) { return knex('notifications').where({ id: notificationId }).update({ read: (0, _helpers2.default)(knex).bool.true() }).then(); }); return function markAsRead(_x) { return _ref.apply(this, arguments); }; })(); /** * Marks all notifications as read (but doesn't archive them) * @return {Promise} */ const markAllAsRead = (() => { var _ref2 = _asyncToGenerator(function* () { return knex('notifications').update({ read: (0, _helpers2.default)(knex).bool.true() }).then(); }); return function markAllAsRead() { return _ref2.apply(this, arguments); }; })(); /** * Get the top 100 (unseen) notifications * @return {Promise<Array<Notification>>} The list of all unseen notifications */ const getInbox = (() => { var _ref3 = _asyncToGenerator(function* () { return knex('notifications').where({ archived: (0, _helpers2.default)(knex).bool.false() }).orderBy('created_on', 'DESC').limit(100).then(function (rows) { return rows.map(function (row) { return fromDatabase(knex, row); }); }); }); return function getInbox() { return _ref3.apply(this, arguments); }; })(); /** * Returns all archived notifications * @return {Promise<Array<Notification>>} The list of all archived notifications */ const getArchived = (() => { var _ref4 = _asyncToGenerator(function* () { return knex('notifications').where({ archived: (0, _helpers2.default)(knex).bool.true() }).orderBy('created_on', 'DESC').limit(100).then(function (rows) { return rows.map(function (row) { return fromDatabase(knex, row); }); }); }); return function getArchived() { return _ref4.apply(this, arguments); }; })(); /** * Archives a single notification * @param {string} notificationId The id of the notification to archive * @return {Promise} */ const archive = (() => { var _ref5 = _asyncToGenerator(function* (notificationId) { return knex('notifications').where({ id: notificationId }).update({ archived: (0, _helpers2.default)(knex).bool.true() }).then(); }); return function archive(_x2) { return _ref5.apply(this, arguments); }; })(); /** * Archives all notifications * @return {Promise} */ const archiveAll = (() => { var _ref6 = _asyncToGenerator(function* () { return knex('notifications').update({ archived: (0, _helpers2.default)(knex).bool.true() }).then(); }); return function archiveAll() { return _ref6.apply(this, arguments); }; })(); // Internal use only // Binds events to actions const _bindEvents = () => { events.on('notifications.getAll', _asyncToGenerator(function* () { events.emit('notifications.all', (yield getInbox())); })); events.on('notifications.read', (() => { var _ref8 = _asyncToGenerator(function* (id) { yield markAsRead(id); events.emit('notifications.all', (yield getInbox())); }); return function (_x3) { return _ref8.apply(this, arguments); }; })()); events.on('notifications.allRead', _asyncToGenerator(function* () { yield markAllAsRead(); events.emit('notifications.all', (yield getInbox())); })); events.on('notifications.trashAll', _asyncToGenerator(function* () { yield archiveAll(); events.emit('notifications.all', (yield getInbox())); })); }; /** * Create and append a new Notification in the Hub. Emits a `notifications.new` event. * @param {string} options.message (required) The body message of the notification * @param {string} options.redirectUrl (optional) The URL the users will be redirected to * when clicking on the notification * @param {string} options.level (optional) The level (info, success, error, warning). Defaults to `info`. * @param {bool} options.enableSound (optional) Whether the notification will trigger a buzzing sound * if a user is currently logged on the dashboard. (defaults to `false`) * @return {Promise} */ const create = (() => { var _ref11 = _asyncToGenerator(function* ({ message, redirectUrl, level, enableSound }) { if (!message || typeof message !== 'string') { throw new Error("'message' is mandatory and should be a string"); } if (!level || typeof level !== 'string' || !_lodash2.default.includes(['info', 'error', 'success'], level.toLowerCase())) { level = 'info'; } else { level = level.toLowerCase(); } const callingFile = getOriginatingModule(); const callingModuleRoot = callingFile && (0, _util.resolveModuleRootPath)(callingFile); const module = _lodash2.default.find(modules, function (mod) { return mod.root === callingModuleRoot; }); let options = { moduleId: 'botpress', icon: 'view_module', name: 'botpress', url: _lodash2.default.isString(redirectUrl) ? redirectUrl : '/' }; if (module) { // because the bot itself can send notifications options = { moduleId: module.name, icon: module.settings.menuIcon, name: module.settings.menuText, url: redirectUrl }; if (!redirectUrl || typeof url !== 'string') { options.url = `/modules/${module.name}`; } } const notification = { id: (0, _nanoid2.default)(), message: message, level: level, moduleId: options.moduleId, icon: options.icon, name: options.name, url: options.url, date: new Date(), sound: enableSound || false, read: false }; yield knex('notifications').insert(toDatabase(knex, notification)).then(); if (logger) { const logMessage = `[notification::${notification.moduleId}] ${notification.message}`; const loggerLevel = logger[level] || logger.info; loggerLevel(logMessage); } if (events) { events.emit('notifications.new', notification); } }); return function create(_x4) { return _ref11.apply(this, arguments); }; })(); return { // ----> Start of legacy API (DEPRECATED as of Botpress 1.1) load: getInbox, send: ({ message, url, level, sound }) => { return create({ message, redirectUrl: url, level, enableSound: sound }); }, // End of legacy API <--- markAsRead, markAllAsRead, archiveAll, archive, getInbox, getArchived, create, // internal API _bindEvents }; }; module.exports = notifications; //# sourceMappingURL=notifications.js.map