1
- import {
2
- ChannelType ,
3
- User ,
4
- GuildMember ,
5
- EmbedBuilder ,
6
- ThreadChannel ,
7
- TextChannel ,
8
- Channel ,
9
- ThreadAutoArchiveDuration ,
10
- } from 'discord.js' ;
1
+ import { ChannelType , ThreadChannel , TextChannel , Channel } from 'discord.js' ;
11
2
import { Bot } from '../bot' ;
12
3
import { HelpThread } from '../entities/HelpThread' ;
13
4
import {
14
- BLOCKQUOTE_GREY ,
15
5
helpForumChannel ,
16
6
helpRequestsChannel ,
17
7
howToGetHelpChannel ,
@@ -22,16 +12,12 @@ import {
22
12
} from '../env' ;
23
13
import { sendWithMessageOwnership } from '../util/send' ;
24
14
25
- const threadExpireHours = ThreadAutoArchiveDuration . OneDay ;
26
- const threadCheckInterval = 60 * 60 * 1000 ;
27
-
28
15
// Use a non-breaking space to force Discord to leave empty lines alone
29
16
const postGuidelines = listify ( `
30
17
How To Get Help
31
- - Create a new post here with your question
32
- - It's always ok to just ask your question; you don't need permission.
18
+ - Create a new post here with your question.
19
+ - It's always ok to just ask your question; you don't need permission.
33
20
- Someone will (hopefully!) come along and help you.
34
- - When your question is resolved, type !close.
35
21
\u200b
36
22
How To Get Better Help
37
23
- Explain what you want to happen and why…
@@ -54,40 +40,13 @@ How To Give Help
54
40
How To Give *Better* Help
55
41
- Get yourself the <@&${ trustedRoleId } > role at <#${ rolesChannelId } >
56
42
- (If you don't like the pings, you can disable role mentions for the server.)
57
- - As a <@&${ trustedRoleId } >, if a thread appears to be resolved, run \`!close\` to close it.
58
- - *Only do this if the asker has indicated that their question has been resolved.*
59
43
60
44
Useful Snippets
61
45
- \`!screenshot\` — for if an asker posts a screenshot of code
62
46
- \`!ask\` — for if an asker only posts "can I get help?"
63
47
` ) ;
64
48
65
- const threadExpireEmbed = new EmbedBuilder ( )
66
- . setColor ( BLOCKQUOTE_GREY )
67
- . setTitle ( 'This help thread expired.' ) . setDescription ( `
68
- If your question was not resolved, you can make a new thread by simply asking your question again. \
69
- Consider rephrasing the question to maximize your chance of getting a good answer. \
70
- If you're not sure how, have a look through [StackOverflow's guide on asking a good question](https://stackoverflow.com/help/how-to-ask).
71
- ` ) ;
72
-
73
- const helperCloseEmbed = ( member : GuildMember ) =>
74
- new EmbedBuilder ( ) . setColor ( BLOCKQUOTE_GREY ) . setDescription ( `
75
- Because your issue seemed to be resolved, this thread was closed by ${ member } .
76
-
77
- If your issue is not resolved, **you can post another message here and the thread will automatically re-open**.
78
-
79
- *If you have a different question, create a new post in <#${ helpForumChannel } >.*
80
- ` ) ;
81
-
82
- const helpPostWelcomeMessage = ( owner : User ) => `
83
- ${ owner } this thread is for your question. \
84
- When it's resolved, please type \`!close\`. \
85
- See <#${ howToGetHelpChannel } > for info on how to get better help.
86
- ` ;
87
-
88
49
export async function helpForumModule ( bot : Bot ) {
89
- const manuallyArchivedThreads = new Set < string > ( ) ;
90
-
91
50
const channel = await bot . client . guilds . cache
92
51
. first ( )
93
52
?. channels . fetch ( helpForumChannel ) ! ;
@@ -116,73 +75,20 @@ export async function helpForumModule(bot: Bot) {
116
75
'in thread' ,
117
76
thread . id ,
118
77
) ;
119
- thread . send ( helpPostWelcomeMessage ( owner . user ) ) ;
120
78
121
79
await HelpThread . create ( {
122
80
threadId : thread . id ,
123
81
ownerId : owner . user . id ,
124
82
} ) . save ( ) ;
125
83
} ) ;
126
84
127
- bot . client . on ( 'threadUpdate' , async thread => {
128
- if (
129
- ! isHelpThread ( thread ) ||
130
- ! ( await thread . fetch ( ) ) . archived ||
131
- manuallyArchivedThreads . delete ( thread . id )
132
- ) {
133
- return ;
134
- }
135
- await onThreadExpire ( thread ) ;
136
- } ) ;
137
-
138
85
bot . client . on ( 'threadDelete' , async thread => {
139
86
if ( ! isHelpThread ( thread ) ) return ;
140
87
await HelpThread . delete ( {
141
88
threadId : thread . id ,
142
89
} ) ;
143
90
} ) ;
144
91
145
- bot . registerCommand ( {
146
- aliases : [ 'close' , 'closed' , 'resolved' , 'resolve' , 'done' , 'solved' ] ,
147
- description : 'Help System: Close an active help thread' ,
148
- async listener ( msg ) {
149
- if (
150
- msg . channel . type !== ChannelType . PublicThread ||
151
- msg . channel . parentId !== forumChannel . id
152
- ) {
153
- return await sendWithMessageOwnership (
154
- msg ,
155
- ':warning: This can only be run in a help thread' ,
156
- ) ;
157
- }
158
-
159
- const threadData = await getHelpThread ( msg . channel . id ) ;
160
-
161
- const isOwner = threadData . ownerId === msg . author . id ;
162
-
163
- if (
164
- isOwner ||
165
- msg . member ?. roles . cache . has ( trustedRoleId ) ||
166
- bot . isMod ( msg . member )
167
- ) {
168
- console . log ( `Closing help thread:` , msg . channel ) ;
169
- await msg . react ( '✅' ) ;
170
- if ( ! isOwner )
171
- await msg . channel . send ( {
172
- content : `<@${ threadData . ownerId } >` ,
173
- embeds : [ helperCloseEmbed ( msg . member ! ) ] ,
174
- } ) ;
175
- manuallyArchivedThreads . add ( msg . channelId ) ;
176
- await msg . channel ?. setArchived ( true ) ;
177
- } else {
178
- return await sendWithMessageOwnership (
179
- msg ,
180
- ':warning: You have to be the asker to close the thread.' ,
181
- ) ;
182
- }
183
- } ,
184
- } ) ;
185
-
186
92
bot . registerCommand ( {
187
93
aliases : [ 'helper' , 'helpers' ] ,
188
94
description : 'Help System: Ping the @Helper role from a help thread' ,
@@ -224,10 +130,22 @@ export async function helpForumModule(bot: Bot) {
224
130
) ;
225
131
}
226
132
133
+ const tagStrings = thread . appliedTags . flatMap ( t => {
134
+ const tag = forumChannel . availableTags . find ( at => at . id === t ) ;
135
+ if ( ! tag ) return [ ] ;
136
+ if ( ! tag . emoji ) return tag . name ;
137
+
138
+ const emoji = tag . emoji . id
139
+ ? `<:${ tag . emoji . name } :${ tag . emoji . id } >`
140
+ : tag . emoji . name ;
141
+ return `${ emoji } ${ tag . name } ` ;
142
+ } ) ;
143
+ const tags = tagStrings ? `(${ tagStrings . join ( ', ' ) } )` : '' ;
144
+
227
145
// The beacons are lit, Gondor calls for aid
228
146
await Promise . all ( [
229
147
helpRequestChannel . send (
230
- `<@&${ trustedRoleId } > ${ msg . channel } ${
148
+ `<@&${ trustedRoleId } > ${ msg . channel } ${ tags } ${
231
149
isTrusted ? comment : ''
232
150
} `,
233
151
) ,
@@ -258,32 +176,6 @@ export async function helpForumModule(bot: Bot) {
258
176
} ,
259
177
} ) ;
260
178
261
- setInterval ( async ( ) => {
262
- const threads = await forumChannel . threads . fetchActive ( ) ;
263
- for ( const thread of threads . threads . values ( ) ) {
264
- const time =
265
- Date . now ( ) -
266
- ( await thread . messages . fetch ( { limit : 1 } ) ) . first ( ) !
267
- . createdTimestamp ;
268
- if ( time >= threadExpireHours * 60 * 1000 ) {
269
- onThreadExpire ( thread ) . catch ( console . error ) ;
270
- }
271
- }
272
- } , threadCheckInterval ) ;
273
-
274
- async function onThreadExpire ( thread : ThreadChannel ) {
275
- const threadData = ( await HelpThread . findOneBy ( {
276
- threadId : thread . id ,
277
- } ) ) ! ;
278
- console . log ( `Help thread expired:` , thread ) ;
279
- await thread . send ( {
280
- content : `<@${ threadData . ownerId } >` ,
281
- embeds : [ threadExpireEmbed ] ,
282
- } ) ;
283
- manuallyArchivedThreads . add ( thread . id ) ;
284
- await thread . setArchived ( true ) ;
285
- }
286
-
287
179
async function getHelpThread ( threadId : string ) {
288
180
const threadData = await HelpThread . findOneBy ( { threadId } ) ;
289
181
0 commit comments