const got = require('got'); 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) { let {body} = await sendMessage(sender, to, message); if (body) body = JSON.parse(body); else body = false; return body; } return false; }; 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, 'alias': sender.nickname, 'text': message }).catch(async error => { if (error.statusCode === 401) { 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`; let {body} = await send(uri, { user: config.user, password: config.password }); if (body) { body = JSON.parse(body); this.auth = body.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 {*} params - Request params * @param {*} options - Request options * * @return {Object} Request response */ async function send(uri, params, options = {}) { if (process.env.NODE_ENV !== 'production') { return new Promise(resolve => { return resolve({ body: JSON.stringify( {statusCode: 200, message: 'Fake notification sent'} ) }); }); } const defaultOptions = { form: params }; if (options) Object.assign(defaultOptions, options); return got.post(uri, 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: {} }; if (login) { options.headers['X-Auth-Token'] = login.authToken; options.headers['X-User-Id'] = login.userId; } return send(uri, body, options); } };