UNPKG

ac-node-hipchat

Version:

A common module plugin for building Atlassian Connect add-ons for HipChat

403 lines (350 loc) 11.5 kB
var rsvp = require('rsvp'); var Promise = rsvp.Promise; var request = require('request'); var check = require('check-types'); var verify = check.verify; var TenantClient = require('./tenant-client'); var defaultScopes = ['send_notification']; function RestClient(httpClient) { this._httpClient = httpClient; } RestClient.prototype._request = function (options) { var self = this; return new Promise(function (resolve, reject) { var method = (options.method || 'GET').toUpperCase(); self._httpClient({ uri: options.uri || options.url, method: method, qs: options.qs, body: options.body, json: true, auth: options.auth }, function (err, response, body) { if (err) return reject(err); var status = response.statusCode; if ((options.expect && status !== options.expect) || status < 200 || status >= 400) { var msg = 'Unexpected response code ' + status + ': ' + method + ' ' + options.url; if (body && body.error && body.error.message) { msg += ': ' + body.error.message; } err = new Error(msg); err.response = response; err.body = body; return reject(err); } resolve({ status: response.statusCode, raw: response, body: body }); }); }); }; RestClient.prototype._get = function (resourceUrl, token, options) { verify.webUrl(resourceUrl); verify.string(token); verify.maybe.object(options); options = options || {}; var qs = exports.optionsToQs(options); return this._request({ url: resourceUrl, method: 'GET', expect: 200, qs: qs, auth: {bearer: token} }).then(function (response) { return response.body; }); }; RestClient.prototype._post = function (resourceUrl, token, options, expect, body) { verify.webUrl(resourceUrl); verify.string(token); verify.maybe.object(options); options = options || {}; return this._request({ url: resourceUrl, method: 'POST', expect: expect, auth: {bearer: token}, body: body }).then(function (response) { return expect === 200 || expect === 201 ? response.body : null; }); }; RestClient.prototype._put = function (resourceUrl, token, options, expect, body) { verify.webUrl(resourceUrl); verify.string(token); verify.maybe.object(options); options = options || {}; return this._request({ url: resourceUrl, method: 'PUT', expect: expect, auth: {bearer: token}, body: body }).then(function (response) { return expect === 200 || expect === 201 ? response.body : null; }); }; RestClient.prototype._del = function (resourceUrl, token) { verify.webUrl(resourceUrl); verify.string(token); return this._request({ url: resourceUrl, method: 'DELETE', expect: 204, auth: {bearer: token} }).then(function (response) { return null; }); }; RestClient.prototype.getCapabilities = function (resourceUrl) { return this._request({ url: resourceUrl, expect: 200 }).then(function (response) { return response.body; }); }; RestClient.prototype.getEmoticons = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.getEmoticon = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.deleteSession = function (resourceUrl, token) { return this._del(resourceUrl, token); }; RestClient.prototype.generateToken = function (resourceUrl, username, password, scopes) { verify.string(username); verify.string(password); scopes = scopes || defaultScopes; return this._request({ url: resourceUrl, method: 'POST', expect: 200, auth: { username: username, password: password }, body: { grant_type: 'client_credentials', scope: scopes.join(' ') } }).then(function (response) { return response.body; }); }; RestClient.prototype.getSession = function (resourceUrl, token) { return this._get(resourceUrl, token); }; RestClient.prototype.getRoomMessage = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; // TODO: share file with room RestClient.prototype.createRoom = function (resourceUrl, token, room) { verify.object(room); room = exports.camelsToSnakes(room); check.map(room, { name: verify.string, topic: verify.string, guest_access: verify.maybe.boolean, owner_user_id: verify.defined, privacy: verify.maybe.string }); return this._post(resourceUrl, token, null, 201, room); }; RestClient.prototype.getRooms = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.getRecentRoomHistory = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.sendNotification = function (resourceUrl, token, message, options) { verify.string(message); options = options || {}; return this._post(resourceUrl, token, options, 204, { message: message, from: options.from, color: options.color || 'yellow', notify: options.notify === true ? options.notify : false, message_format: options.format || 'html', card: options.card }); }; RestClient.prototype.updateRoom = function (resourceUrl, token, room) { verify.object(room); room = exports.camelsToSnakes(room); check.map(room, { name: verify.string, privacy: verify.string, is_archived: verify.boolean, is_guest_accessible: verify.boolean, topic: verify.string, owner: { id: verify.defined } }); return this._put(resourceUrl, token, null, 204, room); }; RestClient.prototype.getRoom = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.deleteRoom = function (resourceUrl, token) { return this._del(resourceUrl, token); }; RestClient.prototype.createRoomWebhook = RestClient.prototype.createWebhook = function (resourceUrl, token, webhook) { verify.object(webhook); webhook = exports.camelsToSnakes(webhook); check.map(webhook, { event: verify.pattern, name: verify.string, url: verify.webUrl, pattern: verify.maybe.string }); return this._post(resourceUrl, token, null, 201, webhook); }; RestClient.prototype.getRoomWebhooks = RestClient.prototype.getWebhooks = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.getRoomStatistics = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.replyToMessage = function (resourceUrl, token, parentMessageId, message) { verify.string(parentMessageId); verify.string(message); return this._post(resourceUrl, token, null, 204, { parentMessageId: parentMessageId, message: message }); }; RestClient.prototype.getRoomMembers = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.setRoomTopic = function (resourceUrl, token, topic) { verify.string(topic); return this._put(resourceUrl, token, null, 204, { topic: topic }); }; RestClient.prototype.shareLinkWithRoom = function (resourceUrl, token, link, message) { verify.string(link); verify.maybe.string(message); return this._put(resourceUrl, token, null, 204, { link: link, message: message }); }; RestClient.prototype.addRoomMember = function (resourceUrl, token) { return this._put(resourceUrl, token, null, 204); }; RestClient.prototype.removeRoomMember = function (resourceUrl, token) { return this._del(resourceUrl, token); }; RestClient.prototype.deleteRoomWebhook = RestClient.prototype.deleteWebhook = function (resourceUrl, token) { return this._del(resourceUrl, token); }; RestClient.prototype.getRoomWebhook = RestClient.prototype.getWebhook = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.getRoomHistory = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.getPrivateChatMessage = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.getRecentPrivateChatHistory = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.updateUserPhoto = function (resourceUrl, token, photo) { verify.string(photo); return this._put(resourceUrl, token, null, 204, { photo: photo }); }; RestClient.prototype.deleteUserPhoto = function (resourceUrl, token) { return this._del(resourceUrl, token); }; RestClient.prototype.forTenant = function (tenant, cache, scopes) { return new TenantClient(this, tenant, cache, scopes); }; RestClient.prototype.updateUser = function (resourceUrl, token, user) { verify.object(user); user = exports.camelsToSnakes(user); check.map(user, { name: verify.string, title: verify.maybe.string, presence: verify.maybe.object, mention_name: verify.maybe.string, is_group_admin: verify.maybe.boolean, timezone: verify.maybe.string, password: verify.maybe.string, email: verify.string }); return this._put(resourceUrl, token, null, 204, user); }; RestClient.prototype.deleteUser = function (resourceUrl, token) { return this._del(resourceUrl, token); }; RestClient.prototype.getUser = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.getUsers = function (resourceUrl, token, options) { return this._get(resourceUrl, token, options); }; RestClient.prototype.glancePushUser = function (resourceUrl, token, data) { return this._post(resourceUrl, token, null, 204, data); }; RestClient.prototype.glancePushRoom = function (resourceUrl, token, data) { return this._post(resourceUrl, token, null, 204, data); }; RestClient.prototype.glancePushGroup = function (resourceUrl, token, data) { return this._post(resourceUrl, token, null, 204, data); }; RestClient.prototype.createUser = function (resourceUrl, token, user) { verify.object(user); user = exports.camelsToSnakes(user); check.map(user, { name: verify.string, title: verify.maybe.string, mention_name: verify.maybe.string, is_group_admin: verify.maybe.boolean, timezone: verify.maybe.string, password: verify.maybe.string, email: verify.string }); return this._post(resourceUrl, token, null, 201, user); }; RestClient.prototype.shareLinkWithUser = function (resourceUrl, token, link, message) { verify.string(link); verify.maybe.string(message); return this._put(resourceUrl, token, null, 204, { link: link, message: message }); }; // TODO: share file with user exports.optionsToQs = function (options) { var qs = {}; Object.keys(options).forEach(function (key) { var dashKey = key.replace(/[A-Z]/g, function ($0) { return '-' + $0.toLowerCase(); }); qs[dashKey] = options[key]; }); return qs; }; exports.camelsToSnakes = function (camels) { var snakes = {}; Object.keys(camels).forEach(function (key) { var snakeKey = key.replace(/[A-Z]/g, function ($0) { return '_' + $0.toLowerCase(); }); snakes[snakeKey] = camels[key]; // TODO: recurse objects and arrays? }); return snakes; }; module.exports = function (httpClient) { return new RestClient(httpClient || request); };