UNPKG

11.1 kBJavaScriptView Raw
1var rsvp = require('rsvp');
2var Promise = rsvp.Promise;
3var request = require('request');
4var check = require('check-types');
5var verify = check.verify;
6var TenantClient = require('./tenant-client');
7
8var defaultScopes = ['send_notification'];
9
10function RestClient(httpClient) {
11 this._httpClient = httpClient;
12}
13
14RestClient.prototype._request = function (options) {
15 var self = this;
16 return new Promise(function (resolve, reject) {
17 var method = (options.method || 'GET').toUpperCase();
18 self._httpClient({
19 uri: options.uri || options.url,
20 method: method,
21 qs: options.qs,
22 body: options.body,
23 json: true,
24 auth: options.auth
25 }, function (err, response, body) {
26 if (err) return reject(err);
27 var status = response.statusCode;
28 if ((options.expect && status !== options.expect) || status < 200 || status >= 400) {
29 var msg = 'Unexpected response code ' + status + ': ' + method + ' ' + options.url;
30 if (body && body.error && body.error.message) {
31 msg += ': ' + body.error.message;
32 }
33 err = new Error(msg);
34 err.response = response;
35 err.body = body;
36 return reject(err);
37 }
38 resolve({
39 status: response.statusCode,
40 raw: response,
41 body: body
42 });
43 });
44 });
45};
46
47RestClient.prototype._get = function (resourceUrl, token, options) {
48 verify.webUrl(resourceUrl);
49 verify.string(token);
50 verify.maybe.object(options);
51 options = options || {};
52 var qs = exports.optionsToQs(options);
53 return this._request({
54 url: resourceUrl,
55 method: 'GET',
56 expect: 200,
57 qs: qs,
58 auth: {bearer: token}
59 }).then(function (response) {
60 return response.body;
61 });
62};
63
64RestClient.prototype._post = function (resourceUrl, token, options, expect, body) {
65 verify.webUrl(resourceUrl);
66 verify.string(token);
67 verify.maybe.object(options);
68 options = options || {};
69 return this._request({
70 url: resourceUrl,
71 method: 'POST',
72 expect: expect,
73 auth: {bearer: token},
74 body: body
75 }).then(function (response) {
76 return expect === 200 || expect === 201 ? response.body : null;
77 });
78};
79
80RestClient.prototype._put = function (resourceUrl, token, options, expect, body) {
81 verify.webUrl(resourceUrl);
82 verify.string(token);
83 verify.maybe.object(options);
84 options = options || {};
85 return this._request({
86 url: resourceUrl,
87 method: 'PUT',
88 expect: expect,
89 auth: {bearer: token},
90 body: body
91 }).then(function (response) {
92 return expect === 200 || expect === 201 ? response.body : null;
93 });
94};
95
96RestClient.prototype._del = function (resourceUrl, token) {
97 verify.webUrl(resourceUrl);
98 verify.string(token);
99 return this._request({
100 url: resourceUrl,
101 method: 'DELETE',
102 expect: 204,
103 auth: {bearer: token}
104 }).then(function (response) {
105 return null;
106 });
107};
108
109RestClient.prototype.getCapabilities = function (resourceUrl) {
110 return this._request({
111 url: resourceUrl,
112 expect: 200
113 }).then(function (response) {
114 return response.body;
115 });
116};
117
118RestClient.prototype.getEmoticons = function (resourceUrl, token, options) {
119 return this._get(resourceUrl, token, options);
120};
121
122RestClient.prototype.getEmoticon = function (resourceUrl, token, options) {
123 return this._get(resourceUrl, token, options);
124};
125
126RestClient.prototype.deleteSession = function (resourceUrl, token) {
127 return this._del(resourceUrl, token);
128};
129
130RestClient.prototype.generateToken = function (resourceUrl, username, password, scopes) {
131 verify.string(username);
132 verify.string(password);
133 scopes = scopes || defaultScopes;
134 return this._request({
135 url: resourceUrl,
136 method: 'POST',
137 expect: 200,
138 auth: {
139 username: username,
140 password: password
141 },
142 body: {
143 grant_type: 'client_credentials',
144 scope: scopes.join(' ')
145 }
146 }).then(function (response) {
147 return response.body;
148 });
149};
150
151RestClient.prototype.getSession = function (resourceUrl, token) {
152 return this._get(resourceUrl, token);
153};
154
155RestClient.prototype.getRoomMessage = function (resourceUrl, token, options) {
156 return this._get(resourceUrl, token, options);
157};
158
159// TODO: share file with room
160
161RestClient.prototype.createRoom = function (resourceUrl, token, room) {
162 verify.object(room);
163 room = exports.camelsToSnakes(room);
164 check.map(room, {
165 name: verify.string,
166 topic: verify.string,
167 guest_access: verify.maybe.boolean,
168 owner_user_id: verify.defined,
169 privacy: verify.maybe.string
170 });
171 return this._post(resourceUrl, token, null, 201, room);
172};
173
174RestClient.prototype.getRooms = function (resourceUrl, token, options) {
175 return this._get(resourceUrl, token, options);
176};
177
178RestClient.prototype.getRecentRoomHistory = function (resourceUrl, token, options) {
179 return this._get(resourceUrl, token, options);
180};
181
182RestClient.prototype.sendNotification = function (resourceUrl, token, message, options) {
183 verify.string(message);
184 options = options || {};
185 return this._post(resourceUrl, token, options, 204, {
186 message: message,
187 color: options.color || 'yellow',
188 notify: options.notify === true ? options.notify : false,
189 message_format: options.format || 'html'
190 });
191};
192
193RestClient.prototype.updateRoom = function (resourceUrl, token, room) {
194 verify.object(room);
195 room = exports.camelsToSnakes(room);
196 check.map(room, {
197 name: verify.string,
198 privacy: verify.string,
199 is_archived: verify.boolean,
200 is_guest_accessible: verify.boolean,
201 topic: verify.string,
202 owner: {
203 id: verify.defined
204 }
205 });
206 return this._put(resourceUrl, token, null, 204, room);
207};
208
209RestClient.prototype.getRoom = function (resourceUrl, token, options) {
210 return this._get(resourceUrl, token, options);
211};
212
213RestClient.prototype.deleteRoom = function (resourceUrl, token) {
214 return this._del(resourceUrl, token);
215};
216
217RestClient.prototype.createRoomWebhook = RestClient.prototype.createWebhook = function (resourceUrl, token, webhook) {
218 verify.object(webhook);
219 webhook = exports.camelsToSnakes(webhook);
220 check.map(webhook, {
221 event: verify.pattern,
222 name: verify.string,
223 url: verify.webUrl,
224 pattern: verify.maybe.string
225 });
226 return this._post(resourceUrl, token, null, 201, webhook);
227};
228
229RestClient.prototype.getRoomWebhooks = RestClient.prototype.getWebhooks = function (resourceUrl, token, options) {
230 return this._get(resourceUrl, token, options);
231};
232
233RestClient.prototype.getRoomStatistics = function (resourceUrl, token, options) {
234 return this._get(resourceUrl, token, options);
235};
236
237RestClient.prototype.replyToMessage = function (resourceUrl, token, parentMessageId, message) {
238 verify.string(parentMessageId);
239 verify.string(message);
240 return this._post(resourceUrl, token, null, 204, {
241 parentMessageId: parentMessageId,
242 message: message
243 });
244};
245
246RestClient.prototype.getRoomMembers = function (resourceUrl, token, options) {
247 return this._get(resourceUrl, token, options);
248};
249
250RestClient.prototype.setRoomTopic = function (resourceUrl, token, topic) {
251 verify.string(topic);
252 return this._put(resourceUrl, token, null, 204, {
253 topic: topic
254 });
255};
256
257RestClient.prototype.shareLinkWithRoom = function (resourceUrl, token, link, message) {
258 verify.string(link);
259 verify.maybe.string(message);
260 return this._put(resourceUrl, token, null, 204, {
261 link: link,
262 message: message
263 });
264};
265
266RestClient.prototype.addRoomMember = function (resourceUrl, token) {
267 return this._put(resourceUrl, token, null, 204);
268};
269
270RestClient.prototype.removeRoomMember = function (resourceUrl, token) {
271 return this._del(resourceUrl, token);
272};
273
274RestClient.prototype.deleteRoomWebhook = RestClient.prototype.deleteWebhook = function (resourceUrl, token) {
275 return this._del(resourceUrl, token);
276};
277
278RestClient.prototype.getRoomWebhook = RestClient.prototype.getWebhook = function (resourceUrl, token, options) {
279 return this._get(resourceUrl, token, options);
280};
281
282RestClient.prototype.getRoomHistory = function (resourceUrl, token, options) {
283 return this._get(resourceUrl, token, options);
284};
285
286RestClient.prototype.getPrivateChatMessage = function (resourceUrl, token, options) {
287 return this._get(resourceUrl, token, options);
288};
289
290RestClient.prototype.getRecentPrivateChatHistory = function (resourceUrl, token, options) {
291 return this._get(resourceUrl, token, options);
292};
293
294RestClient.prototype.updateUserPhoto = function (resourceUrl, token, photo) {
295 verify.string(photo);
296 return this._put(resourceUrl, token, null, 204, {
297 photo: photo
298 });
299};
300
301RestClient.prototype.deleteUserPhoto = function (resourceUrl, token) {
302 return this._del(resourceUrl, token);
303};
304
305RestClient.prototype.forTenant = function (tenant, cache, scopes) {
306 return new TenantClient(this, tenant, cache, scopes);
307};
308
309RestClient.prototype.updateUser = function (resourceUrl, token, user) {
310 verify.object(user);
311 user = exports.camelsToSnakes(user);
312 check.map(user, {
313 name: verify.string,
314 title: verify.maybe.string,
315 presence: verify.maybe.object,
316 mention_name: verify.maybe.string,
317 is_group_admin: verify.maybe.boolean,
318 timezone: verify.maybe.string,
319 password: verify.maybe.string,
320 email: verify.string
321 });
322 return this._put(resourceUrl, token, null, 204, user);
323};
324
325RestClient.prototype.deleteUser = function (resourceUrl, token) {
326 return this._del(resourceUrl, token);
327};
328
329RestClient.prototype.getUser = function (resourceUrl, token, options) {
330 return this._get(resourceUrl, token, options);
331};
332
333RestClient.prototype.getUsers = function (resourceUrl, token, options) {
334 return this._get(resourceUrl, token, options);
335};
336
337RestClient.prototype.createUser = function (resourceUrl, token, user) {
338 verify.object(user);
339 user = exports.camelsToSnakes(user);
340 check.map(user, {
341 name: verify.string,
342 title: verify.maybe.string,
343 mention_name: verify.maybe.string,
344 is_group_admin: verify.maybe.boolean,
345 timezone: verify.maybe.string,
346 password: verify.maybe.string,
347 email: verify.string
348 });
349 return this._post(resourceUrl, token, null, 201, user);
350};
351
352RestClient.prototype.shareLinkWithUser = function (resourceUrl, token, link, message) {
353 verify.string(link);
354 verify.maybe.string(message);
355 return this._put(resourceUrl, token, null, 204, {
356 link: link,
357 message: message
358 });
359};
360
361// TODO: share file with user
362
363exports.optionsToQs = function (options) {
364 var qs = {};
365 Object.keys(options).forEach(function (key) {
366 var dashKey = key.replace(/[A-Z]/g, function ($0) {
367 return '-' + $0.toLowerCase();
368 });
369 qs[dashKey] = options[key];
370 });
371 return qs;
372};
373
374exports.camelsToSnakes = function (camels) {
375 var snakes = {};
376 Object.keys(camels).forEach(function (key) {
377 var snakeKey = key.replace(/[A-Z]/g, function ($0) {
378 return '_' + $0.toLowerCase();
379 });
380 snakes[snakeKey] = camels[key];
381 // TODO: recurse objects and arrays?
382 });
383 return snakes;
384};
385
386module.exports = function (httpClient) {
387 return new RestClient(httpClient || request);
388};