18
18
19
19
import lombok .extern .slf4j .Slf4j ;
20
20
import lombok .val ;
21
+ import net .dv8tion .jda .api .entities .Guild ;
21
22
import net .dv8tion .jda .api .interactions .commands .Command ;
22
23
import net .dv8tion .jda .api .interactions .commands .build .*;
23
24
import net .dv8tion .jda .api .requests .restaction .CommandListUpdateAction ;
25
+ import org .jetbrains .annotations .NotNull ;
26
+ import org .jetbrains .annotations .Nullable ;
24
27
import page .nafuchoco .neobot .api .Launcher ;
25
28
import page .nafuchoco .neobot .api .command .CommandExecutor ;
29
+ import page .nafuchoco .neobot .api .command .CommandValueOption ;
26
30
27
- import java .util .ArrayList ;
28
- import java .util .Arrays ;
29
- import java .util .List ;
31
+ import java .util .*;
30
32
31
33
@ Slf4j
32
34
public abstract class CommandRegistrar {
33
35
private final Launcher launcher ;
34
36
35
- private CommandListUpdateAction updateAction ;
36
- private List <Command > registeredCommands = new ArrayList <>();
37
- private boolean globalCommandListUpdated = false ;
37
+ private CommandListUpdateAction globalUpdateAction ;
38
+ private final Map <Long , CommandListUpdateAction > guildUpdateActions = new HashMap <>();
39
+ private final Map <Long , List <Command >> registeredCommands = new HashMap <>();
40
+ private boolean commandListUpdated = false ;
38
41
39
42
protected CommandRegistrar (Launcher launcher ) {
40
43
this .launcher = launcher ;
44
+ registeredCommands .put (null , new ArrayList <>());
41
45
}
42
46
43
- protected void registerCommandToDiscord (CommandExecutor executor ) {
47
+ protected void registerCommandToDiscord (CommandExecutor executor , Guild guild ) {
44
48
val command = Commands .slash (executor .getName (), executor .getDescription ());
45
49
addCommandOptions (command , executor );
46
- addCommands (command );
50
+ addCommands (guild , command );
47
51
}
48
52
49
- protected void unregisterCommandFromDiscord (CommandExecutor executor ) {
53
+ protected void unregisterCommandFromDiscord (@ NotNull CommandExecutor executor , @ Nullable Guild guild ) {
50
54
if (executor == null )
51
55
return ;
52
56
53
- if (globalCommandListUpdated ) {
54
- var commandData = registeredCommands .stream ().filter (command -> executor .getName ().equals (command .getName ())).findFirst ().orElse (null );
55
- if (commandData != null ) {
56
- launcher .getDiscordApi ().getShardById (0 ).deleteCommandById (commandData .getId ()).queue ();
57
- registeredCommands .remove (commandData );
57
+ if (commandListUpdated ) {
58
+ if (guild == null ) {
59
+ registeredCommands .get (null ).stream ().filter (command -> executor .getName ().equals (command .getName ())).findFirst ().ifPresent (command -> {
60
+ launcher .getDiscordApi ().getShardById (0 ).deleteCommandById (command .getId ()).queue ();
61
+ registeredCommands .get (null ).remove (command );
62
+ });
63
+ } else {
64
+ registeredCommands .get (guild .getIdLong ()).stream ().filter (command -> executor .getName ().equals (command .getName ())).findFirst ().ifPresent (command -> {
65
+ guild .deleteCommandById (command .getId ()).queue ();
66
+ registeredCommands .get (guild .getIdLong ()).remove (command );
67
+ });
58
68
}
59
69
} else {
60
70
throw new IllegalStateException ("Global command list has not been updated yet." );
61
71
}
62
72
}
63
73
64
- private void addCommands (CommandData ... commands ) {
65
- if (globalCommandListUpdated ) {
66
- Arrays .stream (commands ).forEach (command -> {
67
- launcher .getDiscordApi ().getShardById (0 ).upsertCommand (command ).queue (reg -> registeredCommands .add (reg ));
68
- });
74
+ private void addCommands (Guild guild , CommandData ... commands ) {
75
+ if (commandListUpdated ) {
76
+ if (guild == null ) {
77
+ Arrays .stream (commands ).forEach (command -> {
78
+ launcher .getDiscordApi ().getShardById (0 ).upsertCommand (command ).queue (reg -> registeredCommands .get (null ).add (reg ));
79
+ });
80
+ } else {
81
+ Arrays .stream (commands ).forEach (command -> {
82
+ guild .upsertCommand (command ).queue (reg -> registeredCommands .computeIfAbsent (guild .getIdLong (), key -> new ArrayList <>()).add (reg ));
83
+ });
84
+ }
69
85
} else {
70
- if (updateAction == null )
71
- updateAction = launcher .getDiscordApi ().getShardById (0 ).updateCommands ();
86
+ if (guild == null ) {
87
+ if (globalUpdateAction == null )
88
+ globalUpdateAction = launcher .getDiscordApi ().getShardById (0 ).updateCommands ();
89
+ globalUpdateAction .addCommands (commands );
72
90
73
- updateAction .addCommands (commands );
91
+ } else {
92
+ guildUpdateActions .computeIfAbsent (guild .getIdLong (), key -> guild .updateCommands ()).addCommands (commands );
93
+ }
74
94
}
75
95
}
76
96
77
97
private void addCommandOptions (SlashCommandData command , CommandExecutor executor ) {
78
- executor .getValueOptions ().stream ().map (option -> {
98
+ executor .getValueOptions ().stream ()
99
+ .sorted (Comparator .comparing (CommandValueOption ::required ).reversed ())
100
+ .map (option -> {
79
101
val optionData = new OptionData (option .optionType (), option .optionName (), option .optionDescription (), option .required (), option .autoComplete ());
80
102
if (!option .getChoices ().isEmpty ()) {
81
103
switch (option .optionType ()) {
82
- case STRING -> option .getChoices ().forEach ((key , value ) -> optionData .addChoice (key , (String ) value ));
83
- case INTEGER -> option .getChoices ().forEach ((key , value ) -> optionData .addChoice (key , (Long ) value ));
84
- case NUMBER -> option .getChoices ().forEach ((key , value ) -> optionData .addChoice (key , (Double ) value ));
104
+ case STRING ->
105
+ option .getChoices ().forEach ((key , value ) -> optionData .addChoice (key , (String ) value ));
106
+ case INTEGER ->
107
+ option .getChoices ().forEach ((key , value ) -> optionData .addChoice (key , (Long ) value ));
108
+ case NUMBER ->
109
+ option .getChoices ().forEach ((key , value ) -> optionData .addChoice (key , (Double ) value ));
85
110
default -> throw new IllegalStateException ("Unexpected value: " + option .optionType ());
86
111
}
87
112
}
@@ -95,12 +120,14 @@ private void addCommandOptions(SlashCommandData command, CommandExecutor executo
95
120
}
96
121
97
122
protected void queue () {
98
- updateAction .queue (commands -> registeredCommands = new ArrayList <>(commands ));
99
- updateAction = null ;
100
- globalCommandListUpdated = true ;
123
+ globalUpdateAction .queue (commands -> registeredCommands .put (null , new ArrayList <>(commands )));
124
+ guildUpdateActions .forEach ((guildId , action ) -> action .queue (commands -> registeredCommands .computeIfAbsent (guildId , key -> new ArrayList <>(commands ))));
125
+ globalUpdateAction = null ;
126
+ guildUpdateActions .clear ();
127
+ commandListUpdated = true ;
101
128
}
102
129
103
130
protected List <Command > getRegisteredCommands () {
104
- return registeredCommands ;
131
+ return registeredCommands . values (). stream (). flatMap ( Collection :: stream ). toList () ;
105
132
}
106
133
}
0 commit comments