UNPKG

11.5 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 from: options.from,
188 color: options.color || 'yellow',
189 notify: options.notify === true ? options.notify : false,
190 message_format: options.format || 'html',
191 card: options.card
192 });
193};
194
195RestClient.prototype.updateRoom = function (resourceUrl, token, room) {
196 verify.object(room);
197 room = exports.camelsToSnakes(room);
198 check.map(room, {
199 name: verify.string,
200 privacy: verify.string,
201 is_archived: verify.boolean,
202 is_guest_accessible: verify.boolean,
203 topic: verify.string,
204 owner: {
205 id: verify.defined
206 }
207 });
208 return this._put(resourceUrl, token, null, 204, room);
209};
210
211RestClient.prototype.getRoom = function (resourceUrl, token, options) {
212 return this._get(resourceUrl, token, options);
213};
214
215RestClient.prototype.deleteRoom = function (resourceUrl, token) {
216 return this._del(resourceUrl, token);
217};
218
219RestClient.prototype.createRoomWebhook = RestClient.prototype.createWebhook = function (resourceUrl, token, webhook) {
220 verify.object(webhook);
221 webhook = exports.camelsToSnakes(webhook);
222 check.map(webhook, {
223 event: verify.pattern,
224 name: verify.string,
225 url: verify.webUrl,
226 pattern: verify.maybe.string
227 });
228 return this._post(resourceUrl, token, null, 201, webhook);
229};
230
231RestClient.prototype.getRoomWebhooks = RestClient.prototype.getWebhooks = function (resourceUrl, token, options) {
232 return this._get(resourceUrl, token, options);
233};
234
235RestClient.prototype.getRoomStatistics = function (resourceUrl, token, options) {
236 return this._get(resourceUrl, token, options);
237};
238
239RestClient.prototype.replyToMessage = function (resourceUrl, token, parentMessageId, message) {
240 verify.string(parentMessageId);
241 verify.string(message);
242 return this._post(resourceUrl, token, null, 204, {
243 parentMessageId: parentMessageId,
244 message: message
245 });
246};
247
248RestClient.prototype.getRoomMembers = function (resourceUrl, token, options) {
249 return this._get(resourceUrl, token, options);
250};
251
252RestClient.prototype.setRoomTopic = function (resourceUrl, token, topic) {
253 verify.string(topic);
254 return this._put(resourceUrl, token, null, 204, {
255 topic: topic
256 });
257};
258
259RestClient.prototype.shareLinkWithRoom = function (resourceUrl, token, link, message) {
260 verify.string(link);
261 verify.maybe.string(message);
262 return this._put(resourceUrl, token, null, 204, {
263 link: link,
264 message: message
265 });
266};
267
268RestClient.prototype.addRoomMember = function (resourceUrl, token) {
269 return this._put(resourceUrl, token, null, 204);
270};
271
272RestClient.prototype.removeRoomMember = function (resourceUrl, token) {
273 return this._del(resourceUrl, token);
274};
275
276RestClient.prototype.deleteRoomWebhook = RestClient.prototype.deleteWebhook = function (resourceUrl, token) {
277 return this._del(resourceUrl, token);
278};
279
280RestClient.prototype.getRoomWebhook = RestClient.prototype.getWebhook = function (resourceUrl, token, options) {
281 return this._get(resourceUrl, token, options);
282};
283
284RestClient.prototype.getRoomHistory = function (resourceUrl, token, options) {
285 return this._get(resourceUrl, token, options);
286};
287
288RestClient.prototype.getPrivateChatMessage = function (resourceUrl, token, options) {
289 return this._get(resourceUrl, token, options);
290};
291
292RestClient.prototype.getRecentPrivateChatHistory = function (resourceUrl, token, options) {
293 return this._get(resourceUrl, token, options);
294};
295
296RestClient.prototype.updateUserPhoto = function (resourceUrl, token, photo) {
297 verify.string(photo);
298 return this._put(resourceUrl, token, null, 204, {
299 photo: photo
300 });
301};
302
303RestClient.prototype.deleteUserPhoto = function (resourceUrl, token) {
304 return this._del(resourceUrl, token);
305};
306
307RestClient.prototype.forTenant = function (tenant, cache, scopes) {
308 return new TenantClient(this, tenant, cache, scopes);
309};
310
311RestClient.prototype.updateUser = function (resourceUrl, token, user) {
312 verify.object(user);
313 user = exports.camelsToSnakes(user);
314 check.map(user, {
315 name: verify.string,
316 title: verify.maybe.string,
317 presence: verify.maybe.object,
318 mention_name: verify.maybe.string,
319 is_group_admin: verify.maybe.boolean,
320 timezone: verify.maybe.string,
321 password: verify.maybe.string,
322 email: verify.string
323 });
324 return this._put(resourceUrl, token, null, 204, user);
325};
326
327RestClient.prototype.deleteUser = function (resourceUrl, token) {
328 return this._del(resourceUrl, token);
329};
330
331RestClient.prototype.getUser = function (resourceUrl, token, options) {
332 return this._get(resourceUrl, token, options);
333};
334
335RestClient.prototype.getUsers = function (resourceUrl, token, options) {
336 return this._get(resourceUrl, token, options);
337};
338
339RestClient.prototype.glancePushUser = function (resourceUrl, token, data) {
340 return this._post(resourceUrl, token, null, 204, data);
341};
342
343RestClient.prototype.glancePushRoom = function (resourceUrl, token, data) {
344 return this._post(resourceUrl, token, null, 204, data);
345};
346
347RestClient.prototype.glancePushGroup = function (resourceUrl, token, data) {
348 return this._post(resourceUrl, token, null, 204, data);
349};
350
351RestClient.prototype.createUser = function (resourceUrl, token, user) {
352 verify.object(user);
353 user = exports.camelsToSnakes(user);
354 check.map(user, {
355 name: verify.string,
356 title: verify.maybe.string,
357 mention_name: verify.maybe.string,
358 is_group_admin: verify.maybe.boolean,
359 timezone: verify.maybe.string,
360 password: verify.maybe.string,
361 email: verify.string
362 });
363 return this._post(resourceUrl, token, null, 201, user);
364};
365
366RestClient.prototype.shareLinkWithUser = function (resourceUrl, token, link, message) {
367 verify.string(link);
368 verify.maybe.string(message);
369 return this._put(resourceUrl, token, null, 204, {
370 link: link,
371 message: message
372 });
373};
374
375// TODO: share file with user
376
377exports.optionsToQs = function (options) {
378 var qs = {};
379 Object.keys(options).forEach(function (key) {
380 var dashKey = key.replace(/[A-Z]/g, function ($0) {
381 return '-' + $0.toLowerCase();
382 });
383 qs[dashKey] = options[key];
384 });
385 return qs;
386};
387
388exports.camelsToSnakes = function (camels) {
389 var snakes = {};
390 Object.keys(camels).forEach(function (key) {
391 var snakeKey = key.replace(/[A-Z]/g, function ($0) {
392 return '_' + $0.toLowerCase();
393 });
394 snakes[snakeKey] = camels[key];
395 // TODO: recurse objects and arrays?
396 });
397 return snakes;
398};
399
400module.exports = function (httpClient) {
401 return new RestClient(httpClient || request);
402};