const request = require('request-promise-native'); module.exports = Self => { Self.remoteMethodCtx('send', { description: 'Send a RocketChat message', accessType: 'WRITE', accepts: [{ arg: 'to', type: 'String', required: true, description: 'User (@) or channel (#) to send the message' }, { arg: 'message', type: 'String', required: true, description: 'The message' }], returns: { type: 'Object', root: true }, http: { path: `/send`, verb: 'POST' } }); Self.send = async(ctx, to, message) => { const models = Self.app.models; const accessToken = ctx.req.accessToken; const sender = await models.Account.findById(accessToken.userId); const recipient = to.replace('@', ''); if (sender.name != recipient) return sendMessage(sender, to, `@${sender.name}: ${message} `); }; async function sendMessage(sender, channel, message) { const config = await getConfig(); const avatar = `${config.host}/avatar/${sender.name}`; const uri = `${config.api}/chat.postMessage`; return sendAuth(uri, { 'channel': channel, 'avatar': avatar, 'text': message }).catch(async error => { if (error.statusCode === 401 && !this.resendAttempted) { this.resendAttempted = true; this.auth = null; return sendMessage(sender, channel, message); } throw new Error(error.message); }); } /** * Returns a rocketchat token * @return {Object} userId and authToken */ async function getAuthToken() { if (!this.auth || this.auth && !this.auth.authToken) { const config = await getConfig(); const uri = `${config.api}/login`; const res = await send(uri, { user: config.user, password: config.password }); this.auth = res.data; } return this.auth; } /** * Returns a rocketchat config * @return {Object} Auth config */ async function getConfig() { if (!this.chatConfig) { const models = Self.app.models; this.chatConfig = await models.ChatConfig.findOne(); } return this.chatConfig; } /** * Send unauthenticated request * @param {*} uri - Request uri * @param {*} body - Request params * @param {*} options - Request options * * @return {Object} Request response */ async function send(uri, body, options) { if (process.env.NODE_ENV !== 'production') { return new Promise(resolve => { return resolve({statusCode: 200, message: 'Fake notification sent'}); }); } const defaultOptions = { method: 'POST', uri: uri, body: body, headers: {'content-type': 'application/json'}, json: true }; if (options) Object.assign(defaultOptions, options); return request(defaultOptions); } /** * Send authenticated request * @param {*} uri - Request uri * @param {*} body - Request params * * @return {Object} Request response */ async function sendAuth(uri, body) { const login = await getAuthToken(); const options = { headers: {'content-type': 'application/json'} }; if (login) { options.headers['X-Auth-Token'] = login.authToken; options.headers['X-User-Id'] = login.userId; } return send(uri, body, options); } };