@hubot-friends/hubot-slack 0.0.0-development
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/CODE_OF_CONDUCT.md +11 -0
- package/.github/contributing.md +60 -0
- package/.github/issue_template.md +48 -0
- package/.github/maintainers_guide.md +91 -0
- package/.github/pull_request_template.md +8 -0
- package/.github/workflows/ci-build.yml +74 -0
- package/LICENSE +22 -0
- package/README.md +29 -0
- package/docs/Gemfile +2 -0
- package/docs/README.md +15 -0
- package/docs/_config.yml +29 -0
- package/docs/_includes/analytics.html +7 -0
- package/docs/_includes/head.html +33 -0
- package/docs/_includes/page_header.html +20 -0
- package/docs/_includes/side_nav.html +22 -0
- package/docs/_includes/tag_manager.html +13 -0
- package/docs/_layouts/changelog.html +15 -0
- package/docs/_layouts/default.html +47 -0
- package/docs/_layouts/page.html +10 -0
- package/docs/_pages/FAQ.md +63 -0
- package/docs/_pages/about.md +16 -0
- package/docs/_pages/advanced_usage.md +102 -0
- package/docs/_pages/auth.md +44 -0
- package/docs/_pages/basic_usage.md +302 -0
- package/docs/_pages/changelog.html +17 -0
- package/docs/_pages/upgrading.md +49 -0
- package/docs/_posts/2016-07-15-v4.0.0.md +14 -0
- package/docs/_posts/2016-07-19-v4.0.1.md +5 -0
- package/docs/_posts/2016-08-03-v4.0.2.md +4 -0
- package/docs/_posts/2016-09-12-v4.0.3.md +8 -0
- package/docs/_posts/2016-09-12-v4.0.4.md +4 -0
- package/docs/_posts/2016-09-14-v4.0.5.md +4 -0
- package/docs/_posts/2016-09-21-v4.1.0.md +4 -0
- package/docs/_posts/2016-10-12-v4.2.0.md +4 -0
- package/docs/_posts/2016-10-12-v4.2.1.md +4 -0
- package/docs/_posts/2016-11-05-v4.2.2.md +8 -0
- package/docs/_posts/2017-01-05-v4.3.0.md +5 -0
- package/docs/_posts/2017-01-09-v4.3.1.md +5 -0
- package/docs/_posts/2017-02-15-v4.3.2.md +5 -0
- package/docs/_posts/2017-02-17-v4.3.3.md +4 -0
- package/docs/_posts/2017-03-29-v4.3.4.md +5 -0
- package/docs/_posts/2017-08-24-v4.4.0.md +7 -0
- package/docs/_posts/2018-06-08-v4.5.0.md +13 -0
- package/docs/_posts/2018-06-14-v4.5.1.md +4 -0
- package/docs/_posts/2018-07-03-v4.5.2.md +5 -0
- package/docs/_posts/2018-07-17-v4.5.3.md +12 -0
- package/docs/_posts/2018-08-10-v4.5.4.md +7 -0
- package/docs/_posts/2018-10-01-v4.5.5.md +7 -0
- package/docs/_posts/2018-12-21-v4.6.0.md +6 -0
- package/docs/_posts/2019-04-29-v4.7.0.md +6 -0
- package/docs/_posts/2019-04-30-v4.7.1.md +5 -0
- package/docs/_posts/2020-04-03-v4.7.2.md +6 -0
- package/docs/_posts/2020-05-19-v4.8.0.md +10 -0
- package/docs/_posts/2020-10-19-v4.8.1.md +7 -0
- package/docs/_posts/2021-01-26-v4.9.0.md +8 -0
- package/docs/_posts/2022-01-12-v4.10.0.md +8 -0
- package/docs/index.md +93 -0
- package/docs/styles/docs.css +37 -0
- package/package.json +50 -0
- package/slack.js +20 -0
- package/src/SlackAdapter.mjs +302 -0
- package/src/SlackAdapter.test.mjs +342 -0
- package/src/bot.js +526 -0
- package/src/client.js +445 -0
- package/src/extensions.js +82 -0
- package/src/mention.js +15 -0
- package/src/message.js +307 -0
- package/src/testing.mjs +24 -0
- package/test/bot.js +769 -0
- package/test/client.js +446 -0
- package/test/message.js +329 -0
- package/test/stubs.js +388 -0
package/test/stubs.js
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* decaffeinate suggestions:
|
|
3
|
+
* DS101: Remove unnecessary use of Array.from
|
|
4
|
+
* DS102: Remove unnecessary code created because of implicit returns
|
|
5
|
+
* DS207: Consider shorter variations of null checks
|
|
6
|
+
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
7
|
+
*/
|
|
8
|
+
// Setup stubs used by the other tests
|
|
9
|
+
|
|
10
|
+
const SlackBot = require('../src/bot');
|
|
11
|
+
const SlackClient = require('../src/client');
|
|
12
|
+
const {EventEmitter} = require('events');
|
|
13
|
+
const { SlackTextMessage } = require('../src/message');
|
|
14
|
+
// Use Hubot's brain in our stubs
|
|
15
|
+
const {Brain, Robot} = require('hubot');
|
|
16
|
+
|
|
17
|
+
require('../src/extensions');
|
|
18
|
+
|
|
19
|
+
// Stub a few interfaces to grease the skids for tests. These are intentionally
|
|
20
|
+
// as minimal as possible and only provide enough to make the tests possible.
|
|
21
|
+
// Stubs are recreated before each test.
|
|
22
|
+
module.exports = function() {
|
|
23
|
+
const stubs = {};
|
|
24
|
+
|
|
25
|
+
stubs._sendCount = 0;
|
|
26
|
+
stubs.send = (envelope, text, opts) => {
|
|
27
|
+
stubs._room = envelope.room;
|
|
28
|
+
stubs._opts = opts;
|
|
29
|
+
if ((/^[UD@][\d\w]+/.test(stubs._room)) || (stubs._room === stubs.DM.id)) {
|
|
30
|
+
stubs._dmmsg = text;
|
|
31
|
+
} else {
|
|
32
|
+
stubs._msg = text;
|
|
33
|
+
}
|
|
34
|
+
return stubs._sendCount = stubs._sendCount + 1;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// These objects are of conversation shape: https://api.slack.com/types/conversation
|
|
38
|
+
stubs.channel = {
|
|
39
|
+
id: 'C123',
|
|
40
|
+
name: 'general'
|
|
41
|
+
};
|
|
42
|
+
stubs.DM = {
|
|
43
|
+
id: 'D1232',
|
|
44
|
+
is_im: true
|
|
45
|
+
};
|
|
46
|
+
stubs.group = {
|
|
47
|
+
id: 'G12324',
|
|
48
|
+
is_mpim: true
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// These objects are conversation IDs used to siwtch behavior of another stub
|
|
52
|
+
stubs.channelWillFailChatPost = "BAD_CHANNEL";
|
|
53
|
+
|
|
54
|
+
// These objects are of user shape: https://api.slack.com/types/user
|
|
55
|
+
stubs.user = {
|
|
56
|
+
id: 'U123',
|
|
57
|
+
name: 'name', // NOTE: this property is dynamic and should only be used for display purposes
|
|
58
|
+
real_name: 'real_name',
|
|
59
|
+
profile: {
|
|
60
|
+
email: 'email@example.com'
|
|
61
|
+
},
|
|
62
|
+
misc: 'misc'
|
|
63
|
+
};
|
|
64
|
+
stubs.userperiod = {
|
|
65
|
+
name: 'name.lname',
|
|
66
|
+
id: 'U124',
|
|
67
|
+
profile: {
|
|
68
|
+
email: 'name.lname@example.com'
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
stubs.userhyphen = {
|
|
72
|
+
name: 'name-lname',
|
|
73
|
+
id: 'U125',
|
|
74
|
+
profile: {
|
|
75
|
+
email: 'name-lname@example.com'
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
stubs.usernoprofile = {
|
|
79
|
+
name: 'name',
|
|
80
|
+
real_name: 'real_name',
|
|
81
|
+
id: 'U126',
|
|
82
|
+
misc: 'misc'
|
|
83
|
+
};
|
|
84
|
+
stubs.usernoemail = {
|
|
85
|
+
name: 'name',
|
|
86
|
+
real_name: 'real_name',
|
|
87
|
+
id: 'U126',
|
|
88
|
+
profile: {
|
|
89
|
+
foo: 'bar'
|
|
90
|
+
},
|
|
91
|
+
misc: 'misc'
|
|
92
|
+
};
|
|
93
|
+
stubs.userdeleted = {
|
|
94
|
+
name: 'name',
|
|
95
|
+
id: 'U127',
|
|
96
|
+
deleted: true
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
stubs.bot = {
|
|
100
|
+
name: 'testbot',
|
|
101
|
+
user: 'testbot',
|
|
102
|
+
id: 'B123',
|
|
103
|
+
user_id: 'U123'
|
|
104
|
+
};
|
|
105
|
+
stubs.undefined_user_bot = {
|
|
106
|
+
name: 'testbot',
|
|
107
|
+
id: 'B789'
|
|
108
|
+
};
|
|
109
|
+
stubs.slack_bot = {
|
|
110
|
+
name: 'slackbot',
|
|
111
|
+
user: 'slackbot',
|
|
112
|
+
id: 'B01',
|
|
113
|
+
user_id: 'USLACKBOT'
|
|
114
|
+
};
|
|
115
|
+
stubs.self = {
|
|
116
|
+
name: 'self',
|
|
117
|
+
user: 'self',
|
|
118
|
+
user_id: 'U456',
|
|
119
|
+
bot_id: 'B456',
|
|
120
|
+
profile: {
|
|
121
|
+
email: 'self@example.com'
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
stubs.self_bot = {
|
|
125
|
+
name: 'self',
|
|
126
|
+
user: 'self',
|
|
127
|
+
user_id: 'B456',
|
|
128
|
+
profile: {
|
|
129
|
+
email: 'self@example.com'
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
stubs.org_user_not_in_workspace = {
|
|
133
|
+
name: 'name',
|
|
134
|
+
id: 'W123',
|
|
135
|
+
profile: {
|
|
136
|
+
email: 'org_not_in_workspace@example.com'
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
stubs.org_user_not_in_workspace_in_channel = {
|
|
140
|
+
name: 'name',
|
|
141
|
+
id: 'W123',
|
|
142
|
+
profile: {
|
|
143
|
+
email: 'org_not_in_workspace@example.com'
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
stubs.team = {
|
|
147
|
+
name: 'Example Team',
|
|
148
|
+
id: 'T123'
|
|
149
|
+
};
|
|
150
|
+
stubs.expired_timestamp = 1528238205453;
|
|
151
|
+
stubs.event_timestamp = '1360782804.083113';
|
|
152
|
+
|
|
153
|
+
// Slack client
|
|
154
|
+
stubs.client = {
|
|
155
|
+
dataStore: {
|
|
156
|
+
getUserById: id => {
|
|
157
|
+
for (let user of stubs.client.dataStore.users) {
|
|
158
|
+
if (user.id === id) { return user; }
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
getBotById: id => {
|
|
162
|
+
for (let bot of stubs.client.dataStore.bots) {
|
|
163
|
+
if (bot.id === id) { return bot; }
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
getUserByName: name => {
|
|
167
|
+
for (let user of stubs.client.dataStore.users) {
|
|
168
|
+
if (user.name === name) { return user; }
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
getChannelById: id => {
|
|
172
|
+
if (stubs.channel.id === id) { return stubs.channel; }
|
|
173
|
+
},
|
|
174
|
+
getChannelGroupOrDMById: id => {
|
|
175
|
+
if (stubs.channel.id === id) { return stubs.channel; }
|
|
176
|
+
},
|
|
177
|
+
getChannelGroupOrDMByName: name => {
|
|
178
|
+
if (stubs.channel.name === name) { return stubs.channel; }
|
|
179
|
+
for (let dm of stubs.client.dataStore.dms) {
|
|
180
|
+
if (dm.name === name) { return dm; }
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
users: [stubs.user, stubs.self, stubs.userperiod, stubs.userhyphen],
|
|
184
|
+
bots: [stubs.bot],
|
|
185
|
+
dms: [{
|
|
186
|
+
name: 'user2',
|
|
187
|
+
id: 'D5432'
|
|
188
|
+
}
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
stubs.authMock = {
|
|
194
|
+
test: () => {
|
|
195
|
+
return Promise.resolve({
|
|
196
|
+
user_id: stubs.self.id,
|
|
197
|
+
user: stubs.self.name,
|
|
198
|
+
team: stubs.team.name,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
stubs.socket = {
|
|
205
|
+
connected: false,
|
|
206
|
+
async start() {
|
|
207
|
+
this.connected = true;
|
|
208
|
+
},
|
|
209
|
+
disconnect() {
|
|
210
|
+
this.connected = false;
|
|
211
|
+
},
|
|
212
|
+
sendMessage(msg, room) {
|
|
213
|
+
return stubs.send(room, msg);
|
|
214
|
+
},
|
|
215
|
+
dataStore: {
|
|
216
|
+
getUserById(id) {
|
|
217
|
+
switch (id) {
|
|
218
|
+
case stubs.user.user_id: return stubs.user;
|
|
219
|
+
case stubs.bot.user_id: return stubs.bot;
|
|
220
|
+
case stubs.self.user_id: return stubs.self;
|
|
221
|
+
case stubs.self_bot.user_id: return stubs.self_bot;
|
|
222
|
+
default: return undefined;
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
getChannelGroupOrDMById(id) {
|
|
226
|
+
switch (id) {
|
|
227
|
+
case stubs.channel.id: return stubs.channel;
|
|
228
|
+
case stubs.DM.id: return stubs.DM;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
stubs.chatMock = {
|
|
235
|
+
postMessage({channel, text}, opts) {
|
|
236
|
+
if (channel === stubs.channelWillFailChatPost) { return Promise.reject(new Error("stub error")); }
|
|
237
|
+
stubs.send({room: channel, text}, text, opts);
|
|
238
|
+
return Promise.resolve();
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
stubs.conversationsMock = {
|
|
242
|
+
setTopic: (id, topic) => {
|
|
243
|
+
stubs._topic = topic;
|
|
244
|
+
if (stubs.receiveMock.onTopic != null) {
|
|
245
|
+
stubs.receiveMock.onTopic(stubs._topic);
|
|
246
|
+
}
|
|
247
|
+
return Promise.resolve();
|
|
248
|
+
},
|
|
249
|
+
info: conversationId => {
|
|
250
|
+
if (conversationId === stubs.channel.id) {
|
|
251
|
+
return Promise.resolve({ok: true, channel: stubs.channel});
|
|
252
|
+
} else if (conversationId === stubs.DM.id) {
|
|
253
|
+
return Promise.resolve({ok: true, channel: stubs.DM});
|
|
254
|
+
} else if (conversationId === 'C789') {
|
|
255
|
+
return Promise.resolve();
|
|
256
|
+
} else {
|
|
257
|
+
return Promise.reject(new Error('conversationsMock could not match conversation ID'));
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
stubs.botsMock = {
|
|
262
|
+
info: event => {
|
|
263
|
+
const botId = event.bot;
|
|
264
|
+
if (botId === stubs.bot.id) {
|
|
265
|
+
return Promise.resolve({ok: true, bot: stubs.bot});
|
|
266
|
+
} else if (botId === stubs.undefined_user_bot.id) {
|
|
267
|
+
return Promise.resolve({ok: true, bot: stubs.undefined_user_bot});
|
|
268
|
+
} else {
|
|
269
|
+
return Promise.reject(new Error('botsMock could not match bot ID'));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
stubs.usersMock = {
|
|
274
|
+
list: (opts, cb) => {
|
|
275
|
+
stubs._listCount = (stubs != null ? stubs._listCount : undefined) ? stubs._listCount + 1 : 1;
|
|
276
|
+
if (stubs != null ? stubs._listError : undefined) { return cb(new Error('mock error')); }
|
|
277
|
+
if ((opts != null ? opts.cursor : undefined) === 'mock_cursor') {
|
|
278
|
+
return cb(null, stubs.userListPageLast);
|
|
279
|
+
} else {
|
|
280
|
+
return cb(null, stubs.userListPageWithNextCursor);
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
info(params) {
|
|
284
|
+
if (params.user === stubs.user.id) {
|
|
285
|
+
return Promise.resolve({ok: true, user: stubs.user});
|
|
286
|
+
} else if (params.user === stubs.org_user_not_in_workspace.id) {
|
|
287
|
+
return Promise.resolve({ok: true, user: stubs.org_user_not_in_workspace});
|
|
288
|
+
} else if (params.user === 'U789') {
|
|
289
|
+
return Promise.resolve();
|
|
290
|
+
} else {
|
|
291
|
+
return Promise.reject(new Error('usersMock could not match user ID'));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
stubs.userListPageWithNextCursor = {
|
|
296
|
+
members: [{ id: 1 }, { id: 2 }, { id: 4, profile: { bot_id: 'B1' } }],
|
|
297
|
+
response_metadata: {
|
|
298
|
+
next_cursor: 'mock_cursor'
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
stubs.userListPageLast = {
|
|
302
|
+
members: [{ id: 3 }],
|
|
303
|
+
response_metadata: {
|
|
304
|
+
next_cursor: ''
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
stubs.responseUsersList = {
|
|
309
|
+
ok: true,
|
|
310
|
+
members: [stubs.user, stubs.userperiod]
|
|
311
|
+
};
|
|
312
|
+
stubs.wrongResponseUsersList = {
|
|
313
|
+
ok: false,
|
|
314
|
+
members: []
|
|
315
|
+
};
|
|
316
|
+
// Hubot.Robot instance
|
|
317
|
+
stubs.robot = new EventEmitter;
|
|
318
|
+
// noop the logging
|
|
319
|
+
stubs.robot.logger = {
|
|
320
|
+
logs: {},
|
|
321
|
+
log(type, message) {
|
|
322
|
+
if (!this.logs[type]) {
|
|
323
|
+
this.logs[type] = [];
|
|
324
|
+
}
|
|
325
|
+
return this.logs[type].push(message);
|
|
326
|
+
},
|
|
327
|
+
info(message) {
|
|
328
|
+
return this.log('info', message);
|
|
329
|
+
},
|
|
330
|
+
debug(message) {
|
|
331
|
+
return this.log('debug', message);
|
|
332
|
+
},
|
|
333
|
+
error(message) {
|
|
334
|
+
return this.log('error', message);
|
|
335
|
+
},
|
|
336
|
+
warning(message) {
|
|
337
|
+
return this.log('warning', message);
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
// attach a real Brain to the robot
|
|
341
|
+
stubs.robot.brain = new Brain(stubs.robot);
|
|
342
|
+
stubs.robot.name = 'self';
|
|
343
|
+
stubs.robot.listeners = [];
|
|
344
|
+
stubs.robot.listen = Robot.prototype.listen.bind(stubs.robot);
|
|
345
|
+
stubs.robot.hearReaction = Robot.prototype.hearReaction.bind(stubs.robot);
|
|
346
|
+
stubs.robot.fileShared = Robot.prototype.fileShared.bind(stubs.robot);
|
|
347
|
+
stubs.callback = ((() => "done"))();
|
|
348
|
+
|
|
349
|
+
stubs.receiveMock = {
|
|
350
|
+
receive: (message, user) => {
|
|
351
|
+
stubs._received = message;
|
|
352
|
+
if (stubs.receiveMock.onReceived != null) {
|
|
353
|
+
return stubs.receiveMock.onReceived(message);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
// Generate a new slack instance for each test.
|
|
359
|
+
let slackbot = new SlackBot(stubs.robot, {botToken: 'xoxb-faketoken', appToken: 'xapp-faketoken'});
|
|
360
|
+
|
|
361
|
+
Object.assign(slackbot.client, stubs.client);
|
|
362
|
+
Object.assign(slackbot.client.socket, stubs.socket);
|
|
363
|
+
Object.assign(slackbot.client.web.auth, stubs.authMock);
|
|
364
|
+
Object.assign(slackbot.client.web.chat, stubs.chatMock);
|
|
365
|
+
Object.assign(slackbot.client.web.users, stubs.usersMock);
|
|
366
|
+
Object.assign(slackbot.client.web.conversations, stubs.conversationsMock);
|
|
367
|
+
Object.assign(slackbot, stubs.receiveMock);
|
|
368
|
+
slackbot.self = stubs.self;
|
|
369
|
+
|
|
370
|
+
let slacktextmessage = new SlackTextMessage(stubs.self, undefined, undefined, {text: undefined}, stubs.channel.id, undefined, slackbot.client);
|
|
371
|
+
|
|
372
|
+
let slacktextmessage_invalid_conversation = new SlackTextMessage(stubs.self, undefined, undefined, {text: undefined}, 'C888', undefined, slackbot.client);
|
|
373
|
+
|
|
374
|
+
let client = new SlackClient({botToken: 'xoxb-faketoken', appToken: 'xapp-faketoken'}, stubs.robot);
|
|
375
|
+
Object.assign(client.socket, stubs.socket);
|
|
376
|
+
Object.assign(client.web.auth, stubs.authMock);
|
|
377
|
+
Object.assign(client.web.chat, stubs.chatMock);
|
|
378
|
+
Object.assign(client.web.conversations, stubs.conversationsMock);
|
|
379
|
+
Object.assign(client.web.users, stubs.usersMock);
|
|
380
|
+
Object.assign(client.web.bots, stubs.botsMock);
|
|
381
|
+
return {
|
|
382
|
+
client,
|
|
383
|
+
slacktextmessage,
|
|
384
|
+
slackbot,
|
|
385
|
+
stubs,
|
|
386
|
+
slacktextmessage_invalid_conversation
|
|
387
|
+
};
|
|
388
|
+
};
|