1
1
import moment from 'moment/moment'
2
2
import lodash from 'lodash'
3
- import { DiscordMessages , DiscordMembers , DiscordMention } from '../../types/discordTypes'
3
+ import {
4
+ DiscordMessages ,
5
+ DiscordMembers ,
6
+ DiscordMention ,
7
+ DiscordStreamProcessResult ,
8
+ } from '../../types/discordTypes'
4
9
import { DISCORD_CONFIG } from '../../../../config'
5
10
import { DiscordMemberAttributes } from '../../../../database/attributes/member/discord'
6
11
import { MemberAttributeName } from '../../../../database/attributes/member/enums'
@@ -15,15 +20,15 @@ import { IntegrationType, PlatformType } from '../../../../types/integrationEnum
15
20
import { timeout } from '../../../../utils/timing'
16
21
import Operations from '../../../dbOperations/operations'
17
22
import { DiscordGrid } from '../../grid/discordGrid'
18
- import { AddActivitiesSingle } from '../../types/messageTypes'
19
23
import { Channels } from '../../types/regularTypes'
20
24
import getChannels from '../../usecases/discord/getChannels'
21
25
import getMembers from '../../usecases/discord/getMembers'
22
26
import getMessages from '../../usecases/discord/getMessages'
23
- import getThreads from '../../usecases/discord/getThreads'
24
27
import { IntegrationServiceBase } from '../integrationServiceBase'
25
28
import { sendNodeWorkerMessage } from '../../../utils/nodeWorkerSQS'
26
29
import { NodeWorkerIntegrationProcessMessage } from '../../../../types/mq/nodeWorkerIntegrationProcessMessage'
30
+ import { AddActivitiesSingle } from '../../types/messageTypes'
31
+ import { singleOrDefault } from '../../../../utils/arrays'
27
32
28
33
/* eslint class-methods-use-this: 0 */
29
34
@@ -78,13 +83,6 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
78
83
async preprocess ( context : IStepContext ) : Promise < void > {
79
84
const guildId = context . integration . integrationIdentifier
80
85
81
- const threads : Channels = await getThreads (
82
- {
83
- guildId,
84
- token : this . getToken ( context ) ,
85
- } ,
86
- this . logger ( context ) ,
87
- )
88
86
let channelsFromDiscordAPI : Channels = await getChannels (
89
87
{
90
88
guildId,
@@ -105,15 +103,12 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
105
103
return c
106
104
} )
107
105
108
- const channelsWithThreads = channelsFromDiscordAPI . concat ( threads )
109
-
110
106
context . pipelineData = {
111
- channelsFromDiscordAPI ,
112
- channels : channelsWithThreads ,
113
- channelsInfo : channelsWithThreads . reduce ( ( acc , channel ) => {
107
+ settingsChannels : channels ,
108
+ channels : channelsFromDiscordAPI ,
109
+ channelsInfo : channelsFromDiscordAPI . reduce ( ( acc , channel ) => {
114
110
acc [ channel . id ] = {
115
111
name : channel . name ,
116
- thread : ! ! channel . thread ,
117
112
new : ! ! channel . new ,
118
113
}
119
114
return acc
@@ -139,8 +134,9 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
139
134
140
135
return predefined . concat (
141
136
context . pipelineData . channels . map ( ( c ) => ( {
142
- value : c . id ,
137
+ value : 'channel' ,
143
138
metadata : {
139
+ id : c . id ,
144
140
page : '' ,
145
141
} ,
146
142
} ) ) ,
@@ -162,7 +158,7 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
162
158
) {
163
159
try {
164
160
const { fn, arg } = DiscordIntegrationService . getUsecase (
165
- stream . value ,
161
+ stream ,
166
162
context . pipelineData . guildId ,
167
163
)
168
164
const { records, nextPage, limit, timeUntilReset } = await fn (
@@ -176,7 +172,7 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
176
172
)
177
173
178
174
const nextPageStream = nextPage
179
- ? { value : stream . value , metadata : { page : nextPage } }
175
+ ? { value : stream . value , metadata : { ... stream . metadata , page : nextPage } }
180
176
: undefined
181
177
182
178
const sleep = limit <= 1 ? timeUntilReset : undefined
@@ -189,7 +185,7 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
189
185
}
190
186
}
191
187
192
- const activities = this . parseActivities ( stream , context , records )
188
+ const { activities, newStreams } = this . parseActivities ( stream , context , records )
193
189
194
190
const lastRecord = activities . length > 0 ? activities [ activities . length - 1 ] : undefined
195
191
return {
@@ -202,6 +198,7 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
202
198
lastRecord,
203
199
lastRecordTimestamp : lastRecord ? lastRecord . timestamp . getTime ( ) : undefined ,
204
200
nextPageStream,
201
+ newStreams,
205
202
sleep,
206
203
}
207
204
} catch ( err ) {
@@ -244,7 +241,7 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
244
241
)
245
242
246
243
default :
247
- if ( context . pipelineData . channelsInfo [ currentStream . value ] . new ) return false
244
+ if ( context . pipelineData . channelsInfo [ currentStream . metadata . id ] . new ) return false
248
245
249
246
return IntegrationServiceBase . isRetrospectOver (
250
247
lastRecordTimestamp ,
@@ -259,44 +256,36 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
259
256
failedStreams ?: IIntegrationStream [ ] ,
260
257
remainingStreams ?: IIntegrationStream [ ] ,
261
258
) : Promise < void > {
262
- context . integration . settings . channels = context . pipelineData . channelsFromDiscordAPI . map (
263
- ( ch ) => {
264
- const { new : _ , ...raw } = ch
265
- return raw
266
- } ,
267
- )
259
+ context . integration . settings . channels = context . pipelineData . channels . map ( ( ch ) => {
260
+ const { new : _ , ...raw } = ch
261
+ return raw
262
+ } )
268
263
}
269
264
270
265
parseActivities (
271
266
stream : IIntegrationStream ,
272
267
context : IStepContext ,
273
268
records : DiscordMessages | DiscordMembers ,
274
- ) : AddActivitiesSingle [ ] {
269
+ ) : DiscordStreamProcessResult {
275
270
switch ( stream . value ) {
276
271
case 'members' :
277
- return this . parseMembers ( context . integration . tenantId , records as DiscordMembers )
272
+ return this . parseMembers ( context , records as DiscordMembers )
278
273
default :
279
- return this . parseMessages (
280
- context . pipelineData . guildId ,
281
- context . integration . tenantId ,
282
- context . pipelineData . channelsInfo ,
283
- records as DiscordMessages ,
284
- stream ,
285
- )
274
+ return this . parseMessages ( context , records as DiscordMessages , stream )
286
275
}
287
276
}
288
277
289
- parseMembers ( tenantId : string , records : Array < any > ) : Array < AddActivitiesSingle > {
278
+ parseMembers ( context : IStepContext , records : Array < any > ) : DiscordStreamProcessResult {
290
279
// We only need the members if they are not bots
291
- return records . reduce ( ( acc , record ) => {
280
+ const activities : AddActivitiesSingle [ ] = records . reduce ( ( acc , record ) => {
292
281
if ( ! record . user . bot ) {
293
282
let avatarUrl : string | boolean = false
294
283
295
284
if ( record . user . avatar !== null && record . user . avatar !== undefined ) {
296
285
avatarUrl = `https://cdn.discordapp.com/avatars/${ record . user . id } /${ record . user . avatar } .png`
297
286
}
298
287
acc . push ( {
299
- tenant : tenantId ,
288
+ tenant : context . integration . tenantId ,
300
289
platform : PlatformType . DISCORD ,
301
290
type : 'joined_guild' ,
302
291
sourceId : IntegrationServiceBase . generateSourceIdHash (
@@ -325,26 +314,49 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
325
314
}
326
315
return acc
327
316
} , [ ] )
317
+
318
+ return {
319
+ activities,
320
+ newStreams : [ ] ,
321
+ }
328
322
}
329
323
330
324
parseMessages (
331
- guildId : string ,
332
- tenantId : string ,
333
- channelsInfo : any ,
325
+ context : IStepContext ,
334
326
records : DiscordMessages ,
335
327
stream : IIntegrationStream ,
336
- ) : Array < AddActivitiesSingle > {
337
- return records . reduce ( ( acc , record ) => {
328
+ ) : DiscordStreamProcessResult {
329
+ const newStreams : IIntegrationStream [ ] = [ ]
330
+ const activities : AddActivitiesSingle [ ] = records . reduce ( ( acc , record ) => {
338
331
let parent = ''
339
332
340
- // if we're parsing a thread, mark each message as a child
341
- const channelInfo = channelsInfo [ stream . value ]
342
- if ( channelInfo . thread ) {
343
- parent = stream . value
344
- }
333
+ const channelInfo = context . pipelineData . channelsInfo [ stream . metadata . id ]
334
+
335
+ // is the message starting a thread?
336
+ if ( record . thread ) {
337
+ parent = record . thread . id
338
+ newStreams . push ( {
339
+ value : 'thread' ,
340
+ metadata : {
341
+ id : record . thread . id ,
342
+ } ,
343
+ } )
345
344
345
+ context . pipelineData . channelsInfo [ record . thread . id ] = {
346
+ name : context . pipelineData . channelsInfo [ record . channel_id ] . name ,
347
+ new :
348
+ singleOrDefault (
349
+ context . pipelineData . settingsChannels ,
350
+ ( c ) => c . id === record . thread . id ,
351
+ ) === undefined ,
352
+ }
353
+ }
354
+ // if we're parsing a thread, mark each message as a child of this thread
355
+ else if ( stream . value === 'thread' ) {
356
+ parent = stream . metadata . id
357
+ }
346
358
// record.parentId means that it's a reply
347
- if ( record . message_reference && record . message_reference . message_id ) {
359
+ else if ( record . message_reference && record . message_reference . message_id ) {
348
360
parent = record . message_reference . message_id
349
361
}
350
362
@@ -355,7 +367,7 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
355
367
356
368
if ( ! record . author . bot ) {
357
369
const activityObject = {
358
- tenant : tenantId ,
370
+ tenant : context . integration . tenantId ,
359
371
platform : PlatformType . DISCORD ,
360
372
type : 'message' ,
361
373
sourceId : record . id ,
@@ -364,10 +376,10 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
364
376
body : record . content
365
377
? DiscordIntegrationService . replaceMentions ( record . content , record . mentions )
366
378
: '' ,
367
- url : `https://discordapp.com/channels/${ guildId } /${ stream . value } /${ record . id } ` ,
379
+ url : `https://discordapp.com/channels/${ context . pipelineData . guildId } /${ stream . metadata . id } /${ record . id } ` ,
368
380
channel : channelInfo . name ,
369
381
attributes : {
370
- thread : channelInfo . thread ? channelInfo . name : false ,
382
+ thread : record . thread !== undefined || stream . value === 'thread' ,
371
383
reactions : record . reactions ? record . reactions : [ ] ,
372
384
attachments : record . attachments ? record . attachments : [ ] ,
373
385
} ,
@@ -392,11 +404,17 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
392
404
}
393
405
return acc
394
406
} , [ ] )
407
+
408
+ return {
409
+ activities,
410
+ newStreams,
411
+ }
395
412
}
396
413
397
414
/**
398
415
* Parse mentions
399
416
* @param text Message text
417
+ * @param mentions
400
418
* @returns Message text, swapping mention IDs by mentions
401
419
*/
402
420
private static replaceMentions ( text : string , mentions : [ DiscordMention ] | undefined ) : string {
@@ -423,17 +441,20 @@ export class DiscordIntegrationService extends IntegrationServiceBase {
423
441
* @returns The function to call, as well as its main argument
424
442
*/
425
443
private static getUsecase (
426
- stream : string ,
444
+ stream : IIntegrationStream ,
427
445
guildId : string ,
428
446
) : {
429
447
fn : Function
430
448
arg : any
431
449
} {
432
- switch ( stream ) {
450
+ switch ( stream . value ) {
433
451
case 'members' :
434
452
return { fn : getMembers , arg : { guildId } }
453
+ case 'channel' :
454
+ case 'thread' :
455
+ return { fn : getMessages , arg : { channelId : stream . metadata . id } }
435
456
default :
436
- return { fn : getMessages , arg : { channelId : stream } }
457
+ throw new Error ( `Unknown stream ${ stream . value } !` )
437
458
}
438
459
}
439
460
}
0 commit comments