1414import org .togetherjava .tjbot .config .HelpSystemConfig ;
1515
1616import java .awt .Color ;
17- import java .util .List ;
18- import java .util .Optional ;
19- import java .util .StringJoiner ;
17+ import java .util .*;
2018import java .util .concurrent .TimeUnit ;
2119import java .util .function .Predicate ;
20+ import java .util .regex .Matcher ;
2221import java .util .regex .Pattern ;
22+ import java .util .stream .Collectors ;
2323
2424// FIXME Javadoc
2525public final class HelpThreadOverviewUpdater extends MessageReceiverAdapter implements Routine {
2626 private static final Logger logger = LoggerFactory .getLogger (HelpThreadOverviewUpdater .class );
2727
2828 private static final Color AMBIENT_COLOR = Color .decode ("#CCCC00" );
29+ // FIXME Reduce code duplication with similar pattern in ChangeHelpCategoryCommand
30+ private static final Pattern EXTRACT_CATEGORY_PATTERN =
31+ Pattern .compile ("(?:\\ [(?<category>.+)] )?(?<title>.+)" );
2932
3033 private final HelpSystemConfig config ;
3134 private final Predicate <String > isOverviewChannelName ;
@@ -108,22 +111,15 @@ private void updateOverview(@NotNull Guild guild) {
108111 return maybeChannel ;
109112 }
110113
111- private static void updateOverview (@ NotNull IThreadContainer stagingChannel ,
114+ private void updateOverview (@ NotNull IThreadContainer stagingChannel ,
112115 @ NotNull MessageChannel overviewChannel ) {
113116 List <ThreadChannel > activeThreads = stagingChannel .getThreadChannels ()
114117 .stream ()
115118 .filter (Predicate .not (ThreadChannel ::isArchived ))
116119 .toList ();
117120
118- // FIXME Do not add prefix if empty... (this should be reworked for nicer UI anyways)
119- StringJoiner description = new StringJoiner ("\n • " , "• " , "" );
120-
121- for (ThreadChannel thread : activeThreads ) {
122- description .add (thread .getAsMention ());
123- }
124-
125121 MessageEmbed embed = new EmbedBuilder ().setTitle ("Active questions" )
126- .setDescription (description . toString ( ))
122+ .setDescription (createDescription ( activeThreads ))
127123 .setColor (AMBIENT_COLOR )
128124 .build ();
129125
@@ -137,6 +133,40 @@ private static void updateOverview(@NotNull IThreadContainer stagingChannel,
137133 }).queue ();
138134 }
139135
136+ private @ NotNull String createDescription (@ NotNull Collection <ThreadChannel > activeThreads ) {
137+ if (activeThreads .isEmpty ()) {
138+ return "Currently none." ;
139+ }
140+
141+ List <String > allCategories = config .getCategories ();
142+
143+ return activeThreads .stream ()
144+ .collect (Collectors
145+ .groupingBy (thread -> getCategoryOfChannel (thread ).orElse ("Uncategorized" )))
146+ .entrySet ()
147+ .stream ()
148+ .map (CategoryWithThreads ::ofEntry )
149+ .sorted (Comparator .comparingInt (categoryWithThreads -> {
150+ // Order based on config, unknown categories last
151+ int indexOfCategory = allCategories .indexOf (categoryWithThreads .category );
152+ if (indexOfCategory == -1 ) {
153+ return Integer .MAX_VALUE ;
154+ }
155+ return indexOfCategory ;
156+ }))
157+ .map (CategoryWithThreads ::toDiscordString )
158+ .collect (Collectors .joining ("\n \n " ));
159+ }
160+
161+ private static @ NotNull Optional <String > getCategoryOfChannel (@ NotNull Channel channel ) {
162+ Matcher matcher = EXTRACT_CATEGORY_PATTERN .matcher (channel .getName ());
163+ if (!matcher .find ()) {
164+ return Optional .empty ();
165+ }
166+
167+ return Optional .ofNullable (matcher .group ("category" ));
168+ }
169+
140170 private static @ NotNull RestAction <Optional <Message >> getLastMessage (
141171 @ NotNull MessageChannel channel ) {
142172 return channel .getHistory ().retrievePast (1 ).map (messages -> messages .stream ().findFirst ());
@@ -146,4 +176,22 @@ private enum ChannelType {
146176 OVERVIEW ,
147177 STAGING
148178 }
179+
180+ private record CategoryWithThreads (@ NotNull String category ,
181+ @ NotNull List <ThreadChannel > threads ) {
182+
183+ String toDiscordString () {
184+ String threadListText = threads .stream ()
185+ .map (ThreadChannel ::getAsMention )
186+ .collect (Collectors .joining ("\n • " , "• " , "" ));
187+
188+ return "**%s**:%n%s" .formatted (category , threadListText );
189+ }
190+
191+ static @ NotNull CategoryWithThreads ofEntry (
192+ Map .@ NotNull Entry <String , ? extends List <ThreadChannel >> categoryAndThreads ) {
193+ return new CategoryWithThreads (categoryAndThreads .getKey (),
194+ categoryAndThreads .getValue ());
195+ }
196+ }
149197}
0 commit comments