Skip to content

Commit 2fe1ea8

Browse files
authored
Merge pull request #106 from typescript-community/empty-ongoing
Put channels into dormant after 5 minutes if ongoing channel becomes empty
2 parents 5180d7a + e43536c commit 2fe1ea8

File tree

3 files changed

+66
-12
lines changed

3 files changed

+66
-12
lines changed

.env.example

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ ASK_COOLDOWN_ROLE=
2222

2323
CHANNEL_NAMES=list,help,channel,names,here,seperated,by,commas
2424

25-
# In seconds
25+
# Following variables are in milliseconds
2626
DORMANT_CHANNEL_TIMEOUT=
27-
# In milliseconds
2827
DORMANT_CHANNEL_LOOP=
28+
ONGOING_EMPTY_TIMEOUT=

src/env.ts

+4
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,13 @@ export const trustedRoleId = process.env.TRUSTED_ROLE_ID!;
2828
export const askHelpChannelId = process.env.ASK_HELP_CHANNEL!;
2929

3030
export const channelNames = process.env.CHANNEL_NAMES!.split(',');
31+
3132
export const dormantChannelTimeout = parseInt(
3233
process.env.DORMANT_CHANNEL_TIMEOUT!,
3334
);
3435
export const dormantChannelLoop = parseInt(process.env.DORMANT_CHANNEL_LOOP!);
36+
37+
export const ongoingEmptyTimeout = parseInt(process.env.ONGOING_EMPTY_TIMEOUT!);
38+
3539
export const TS_BLUE = '#007ACC';
3640
export const GREEN = '#77b155';

src/modules/helpchan.ts

+60-10
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
dormantChannelTimeout,
2424
dormantChannelLoop,
2525
askHelpChannelId,
26+
ongoingEmptyTimeout,
2627
} from '../env';
2728
import { isTrustedMember } from '../util/inhibitors';
2829

@@ -66,6 +67,7 @@ export class HelpChanModule extends Module {
6667
.setDescription(DORMANT_MESSAGE);
6768

6869
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
6971

7072
private getChannelName(guild: Guild) {
7173
const takenChannelNames = guild.channels.cache
@@ -81,13 +83,67 @@ export class HelpChanModule extends Module {
8183
return `${this.CHANNEL_PREFIX}${decidedChannel}`;
8284
}
8385

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+
8495
@listener({ event: 'ready' })
8596
async startDormantLoop() {
8697
setInterval(() => {
8798
this.checkDormantPossibilities();
8899
}, dormantChannelLoop);
89100
}
90101

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+
91147
async moveChannel(channel: TextChannel, category: string) {
92148
const parent = channel.guild.channels.resolve(category);
93149
if (parent == null) return;
@@ -248,20 +304,14 @@ export class HelpChanModule extends Module {
248304
}
249305

250306
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();
259309

260310
const diff =
261-
(Date.now() - messages.array()[0].createdAt.getTime()) / 1000;
311+
Date.now() - (messages.first()?.createdAt.getTime() ?? 0);
262312

263313
if (diff > dormantChannelTimeout)
264-
await this.markChannelAsDormant(channel as TextChannel);
314+
await this.markChannelAsDormant(channel);
265315
}
266316
}
267317

0 commit comments

Comments
 (0)