@@ -23,6 +23,7 @@ import {
23
23
dormantChannelTimeout ,
24
24
dormantChannelLoop ,
25
25
askHelpChannelId ,
26
+ ongoingEmptyTimeout ,
26
27
} from '../env' ;
27
28
import { isTrustedMember } from '../util/inhibitors' ;
28
29
@@ -66,6 +67,7 @@ export class HelpChanModule extends Module {
66
67
. setDescription ( DORMANT_MESSAGE ) ;
67
68
68
69
busyChannels : Set < string > = new Set ( ) ; // a lock to eliminate race conditions
70
+ ongoingEmptyTimeouts : Map < string , NodeJS . Timeout > = new Map ( ) ; // a lock used to prevent multiple timeouts running on the same channel
69
71
70
72
private getChannelName ( guild : Guild ) {
71
73
const takenChannelNames = guild . channels . cache
@@ -81,13 +83,67 @@ export class HelpChanModule extends Module {
81
83
return `${ this . CHANNEL_PREFIX } ${ decidedChannel } ` ;
82
84
}
83
85
86
+ private getOngoingChannels ( ) {
87
+ return this . client . channels . cache
88
+ . filter (
89
+ channel =>
90
+ ( channel as TextChannel ) . parentID === categories . ongoing ,
91
+ )
92
+ . array ( ) as TextChannel [ ] ;
93
+ }
94
+
84
95
@listener ( { event : 'ready' } )
85
96
async startDormantLoop ( ) {
86
97
setInterval ( ( ) => {
87
98
this . checkDormantPossibilities ( ) ;
88
99
} , dormantChannelLoop ) ;
89
100
}
90
101
102
+ @listener ( { event : 'ready' } )
103
+ async initialCheckEmptyOngoing ( ) {
104
+ for ( const channel of this . getOngoingChannels ( ) ) {
105
+ if ( await this . checkEmptyOngoing ( channel ) ) {
106
+ await this . startEmptyTimeout ( channel ) ;
107
+ }
108
+ }
109
+ }
110
+
111
+ // Utility function used to check if there are no messages in an ongoing channel, meaning the bot
112
+ // is the most recent message. This will be caused if somebody deletes their message after they
113
+ // claim a channel.
114
+ async checkEmptyOngoing ( channel : TextChannel ) {
115
+ const messages = await channel . messages . fetch ( ) ;
116
+
117
+ return messages . first ( ) ?. author . id === this . client . user ?. id ;
118
+ }
119
+
120
+ async startEmptyTimeout ( channel : TextChannel ) {
121
+ const existingTimeout = this . ongoingEmptyTimeouts . get ( channel . id ) ;
122
+ if ( existingTimeout ) clearTimeout ( existingTimeout ) ;
123
+
124
+ const timeout = setTimeout ( async ( ) => {
125
+ this . ongoingEmptyTimeouts . delete ( channel . id ) ;
126
+
127
+ if ( await this . checkEmptyOngoing ( channel ) ) {
128
+ await this . markChannelAsDormant ( channel ) ;
129
+ }
130
+ } , ongoingEmptyTimeout ) ;
131
+
132
+ this . ongoingEmptyTimeouts . set ( channel . id , timeout ) ;
133
+ }
134
+
135
+ @listener ( { event : 'messageDelete' } )
136
+ async onMessageDeleted ( msg : Message ) {
137
+ if (
138
+ msg . channel . type !== 'text' ||
139
+ ! msg . channel . parentID ||
140
+ msg . channel . parentID !== categories . ongoing
141
+ )
142
+ return ;
143
+
144
+ await this . startEmptyTimeout ( msg . channel ) ;
145
+ }
146
+
91
147
async moveChannel ( channel : TextChannel , category : string ) {
92
148
const parent = channel . guild . channels . resolve ( category ) ;
93
149
if ( parent == null ) return ;
@@ -248,20 +304,14 @@ export class HelpChanModule extends Module {
248
304
}
249
305
250
306
private async checkDormantPossibilities ( ) {
251
- const ongoingChannels = this . client . channels . cache . filter ( channel => {
252
- if ( channel . type === 'dm' ) return false ;
253
-
254
- return ( channel as TextChannel ) . parentID === categories . ongoing ;
255
- } ) ;
256
-
257
- for ( const channel of ongoingChannels . array ( ) ) {
258
- const messages = await ( channel as TextChannel ) . messages . fetch ( ) ;
307
+ for ( const channel of this . getOngoingChannels ( ) ) {
308
+ const messages = await channel . messages . fetch ( ) ;
259
309
260
310
const diff =
261
- ( Date . now ( ) - messages . array ( ) [ 0 ] . createdAt . getTime ( ) ) / 1000 ;
311
+ Date . now ( ) - ( messages . first ( ) ? .createdAt . getTime ( ) ?? 0 ) ;
262
312
263
313
if ( diff > dormantChannelTimeout )
264
- await this . markChannelAsDormant ( channel as TextChannel ) ;
314
+ await this . markChannelAsDormant ( channel ) ;
265
315
}
266
316
}
267
317
0 commit comments