9
9
import net .dv8tion .jda .api .events .interaction .command .SlashCommandInteractionEvent ;
10
10
import net .dv8tion .jda .api .interactions .callbacks .IDeferrableCallback ;
11
11
import net .dv8tion .jda .api .interactions .callbacks .IReplyCallback ;
12
+ import net .dv8tion .jda .api .interactions .commands .OptionMapping ;
13
+ import net .dv8tion .jda .api .interactions .commands .OptionType ;
14
+ import net .dv8tion .jda .api .interactions .commands .build .OptionData ;
12
15
import org .jetbrains .annotations .NotNull ;
13
16
import org .jetbrains .annotations .Nullable ;
14
17
import org .jooq .Records ;
20
23
import org .togetherjava .tjbot .config .Config ;
21
24
import org .togetherjava .tjbot .db .Database ;
22
25
23
- import java .time .Instant ;
24
- import java .time .ZoneOffset ;
25
- import java .time .ZonedDateTime ;
26
+ import java .time .*;
26
27
import java .time .format .TextStyle ;
27
- import java .time .temporal .TemporalAdjusters ;
28
- import java .util .Collection ;
29
- import java .util .List ;
30
- import java .util .Locale ;
31
- import java .util .Map ;
28
+ import java .util .*;
32
29
import java .util .function .Function ;
33
30
import java .util .function .IntFunction ;
34
31
import java .util .function .Predicate ;
47
44
public final class TopHelpersCommand extends SlashCommandAdapter {
48
45
private static final Logger logger = LoggerFactory .getLogger (TopHelpersCommand .class );
49
46
private static final String COMMAND_NAME = "top-helpers" ;
47
+ private static final String MONTH_OPTION = "at-month" ;
50
48
private static final int TOP_HELPER_LIMIT = 20 ;
51
49
52
50
private final Database database ;
@@ -59,8 +57,16 @@ public final class TopHelpersCommand extends SlashCommandAdapter {
59
57
* @param config the config to use for this
60
58
*/
61
59
public TopHelpersCommand (@ NotNull Database database , @ NotNull Config config ) {
62
- super (COMMAND_NAME , "Lists top helpers for the last month" , SlashCommandVisibility .GUILD );
63
- // TODO Add options to optionally pick a time range once JDA/Discord offers a date-picker
60
+ super (COMMAND_NAME , "Lists top helpers for the last month, or a given month" ,
61
+ SlashCommandVisibility .GUILD );
62
+
63
+ OptionData monthData = new OptionData (OptionType .STRING , MONTH_OPTION ,
64
+ "the month to compute for, by default the last month" , false );
65
+ Arrays .stream (Month .values ())
66
+ .forEach (month -> monthData .addChoice (
67
+ month .getDisplayName (TextStyle .FULL_STANDALONE , Locale .US ), month .name ()));
68
+ getData ().addOptions (monthData );
69
+
64
70
hasRequiredRole = Pattern .compile (config .getSoftModerationRolePattern ()).asMatchPredicate ();
65
71
this .database = database ;
66
72
}
@@ -70,8 +76,9 @@ public void onSlashCommand(@NotNull SlashCommandInteractionEvent event) {
70
76
if (!handleHasAuthorRole (event .getMember (), event )) {
71
77
return ;
72
78
}
79
+ OptionMapping atMonthData = event .getOption (MONTH_OPTION );
73
80
74
- TimeRange timeRange = computeDefaultTimeRange ( );
81
+ TimeRange timeRange = computeTimeRange ( computeMonth ( atMonthData ) );
75
82
List <TopHelperResult > topHelpers =
76
83
computeTopHelpersDescending (event .getGuild ().getIdLong (), timeRange );
77
84
@@ -102,16 +109,31 @@ private boolean handleHasAuthorRole(@NotNull Member author, @NotNull IReplyCallb
102
109
return false ;
103
110
}
104
111
105
- private static @ NotNull TimeRange computeDefaultTimeRange () {
106
- // Last month
107
- ZonedDateTime start = Instant .now ()
108
- .atZone (ZoneOffset .UTC )
109
- .minusMonths (1 )
110
- .with (TemporalAdjusters .firstDayOfMonth ());
111
- ZonedDateTime end = start .with (TemporalAdjusters .lastDayOfMonth ());
112
- String description = start .getMonth ().getDisplayName (TextStyle .FULL_STANDALONE , Locale .US );
112
+ private static @ NotNull Month computeMonth (@ Nullable OptionMapping atMonthData ) {
113
+ if (atMonthData != null ) {
114
+ return Month .valueOf (atMonthData .getAsString ());
115
+ }
113
116
114
- return new TimeRange (start .toInstant (), end .toInstant (), description );
117
+ // Previous month
118
+ return Instant .now ().atZone (ZoneOffset .UTC ).minusMonths (1 ).getMonth ();
119
+ }
120
+
121
+ private static @ NotNull TimeRange computeTimeRange (@ NotNull Month atMonth ) {
122
+ ZonedDateTime now = Instant .now ().atZone (ZoneOffset .UTC );
123
+
124
+ int atYear = now .getYear ();
125
+ // E.g. using November, while it is March 2022, should use November 2021
126
+ if (atMonth .compareTo (now .getMonth ()) > 0 ) {
127
+ atYear --;
128
+ }
129
+ YearMonth atYearMonth = YearMonth .of (atYear , atMonth );
130
+
131
+ Instant start = atYearMonth .atDay (1 ).atTime (LocalTime .MIN ).toInstant (ZoneOffset .UTC );
132
+ Instant end = atYearMonth .atEndOfMonth ().atTime (LocalTime .MAX ).toInstant (ZoneOffset .UTC );
133
+ String description = "%s %d"
134
+ .formatted (atMonth .getDisplayName (TextStyle .FULL_STANDALONE , Locale .US ), atYear );
135
+
136
+ return new TimeRange (start , end , description );
115
137
}
116
138
117
139
private @ NotNull List <TopHelperResult > computeTopHelpersDescending (long guildId ,
@@ -187,9 +209,11 @@ private static void handleTopHelpers(@NotNull Collection<TopHelperResult> topHel
187
209
private record TimeRange (Instant start , Instant end , String description ) {
188
210
}
189
211
212
+
190
213
private record TopHelperResult (long authorId , int messageCount ) {
191
214
}
192
215
216
+
193
217
private record ColumnSetting (String headerName , HorizontalAlign alignment ) {
194
218
}
195
219
}
0 commit comments