Skip to content

Commit a8a572d

Browse files
authored
Merge pull request #9 from HyScript7/feat/logcommands
2 parents 1465677 + bd6c722 commit a8a572d

9 files changed

Lines changed: 245 additions & 3 deletions

File tree

src/main/java/io/github/hyscript7/scriptutils/domain/discord/commands/ChannelContext.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,11 @@ public interface ChannelContext {
7575
* Deletes the channel.
7676
*/
7777
void delete();
78+
79+
/**
80+
* Creates a new webhook and returns its url
81+
* @param name The name for the webhook
82+
* @return The URL (token included)
83+
*/
84+
String createWebhook(String name);
7885
}

src/main/java/io/github/hyscript7/scriptutils/domain/discord/commands/GuildContext.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,5 +126,4 @@ public interface GuildContext {
126126
* @return The new roles context
127127
*/
128128
RoleContext createRole(String name, int color, boolean mentionable, boolean distinct, @Nullable Long positionedAfter);
129-
130129
}

src/main/java/io/github/hyscript7/scriptutils/infrastructure/discord/SlashChannelContext.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.Optional;
44

5+
import net.dv8tion.jda.api.entities.channel.attribute.IWebhookContainer;
56
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
67
import org.jetbrains.annotations.Nullable;
78

@@ -109,4 +110,14 @@ public void delete() {
109110
}
110111
}
111112

113+
@Override
114+
public String createWebhook(String name) {
115+
if (!(channel instanceof IWebhookContainer wc)) {
116+
throw new UnsupportedOperationException(
117+
"Cannot create a webhook on a channel of type " + channel.getType()
118+
);
119+
}
120+
return wc.createWebhook(name).complete().getUrl();
121+
}
122+
112123
}

src/main/java/io/github/hyscript7/scriptutils/modules/logging/LoggingConfiguration.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package io.github.hyscript7.scriptutils.modules.logging;
22

3+
import io.github.hyscript7.scriptutils.modules.logging.internal.commands.LoggingCommandGroup;
4+
import io.github.hyscript7.scriptutils.modules.logging.internal.commands.LoggingDisableSubcommand;
5+
import io.github.hyscript7.scriptutils.modules.logging.internal.commands.LoggingEnableSubcommand;
6+
import io.github.hyscript7.scriptutils.modules.logging.internal.commands.LoggingStatusSubcommand;
7+
import io.github.hyscript7.scriptutils.modules.logging.internal.services.GuildLoggingSettingsService;
38
import org.springframework.context.annotation.Bean;
49
import org.springframework.context.annotation.Configuration;
510

@@ -11,6 +16,30 @@
1116

1217
@Configuration
1318
public class LoggingConfiguration {
19+
@Bean
20+
LoggingStatusSubcommand loggingStatusSubcommand(GuildLoggingSettingsService guildLoggingSettingsService) {
21+
return new LoggingStatusSubcommand(guildLoggingSettingsService);
22+
}
23+
24+
@Bean
25+
LoggingEnableSubcommand loggingEnableSubcommand(GuildLoggingSettingsService guildLoggingSettingsService) {
26+
return new LoggingEnableSubcommand(guildLoggingSettingsService);
27+
}
28+
29+
@Bean
30+
LoggingDisableSubcommand loggingDisableSubcommand(GuildLoggingSettingsService guildLoggingSettingsService) {
31+
return new LoggingDisableSubcommand(guildLoggingSettingsService);
32+
}
33+
34+
@Bean
35+
LoggingCommandGroup loggingCommandGroup(LoggingStatusSubcommand loggingStatusSubcommand, LoggingEnableSubcommand loggingEnableSubcommand, LoggingDisableSubcommand loggingDisableSubcommand) {
36+
LoggingCommandGroup loggingCommandGroup = new LoggingCommandGroup();
37+
loggingCommandGroup.addSubcommand(loggingStatusSubcommand);
38+
loggingCommandGroup.addSubcommand(loggingDisableSubcommand);
39+
loggingCommandGroup.addSubcommand(loggingEnableSubcommand);
40+
return loggingCommandGroup;
41+
}
42+
1443
@Bean
1544
MemberLoggingListener memberLoggingListener(DiscordLoggingService discordLoggingService) {
1645
return new MemberLoggingListener(discordLoggingService);
@@ -32,13 +61,19 @@ VoiceLoggingListener voiceLoggingListener(DiscordLoggingService discordLoggingSe
3261
}
3362

3463
@Bean
35-
LoggingModule loggingModule(MemberLoggingListener memberLoggingListener,
36-
ModerationLoggingListener moderationLoggingListener, ServerLoggingListener serverLoggingListener, VoiceLoggingListener voiceLoggingListener) {
64+
LoggingModule loggingModule(
65+
MemberLoggingListener memberLoggingListener,
66+
ModerationLoggingListener moderationLoggingListener,
67+
ServerLoggingListener serverLoggingListener,
68+
VoiceLoggingListener voiceLoggingListener,
69+
LoggingCommandGroup loggingCommandGroup
70+
) {
3771
LoggingModule loggingModule = new LoggingModule();
3872
loggingModule.addEventListener(memberLoggingListener);
3973
loggingModule.addEventListener(moderationLoggingListener);
4074
loggingModule.addEventListener(serverLoggingListener);
4175
loggingModule.addEventListener(voiceLoggingListener);
76+
loggingModule.addCommand(loggingCommandGroup);
4277
return loggingModule;
4378
}
4479

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package io.github.hyscript7.scriptutils.modules.logging.internal.commands;
2+
3+
import io.github.hyscript7.scriptutils.domain.discord.commands.*;
4+
import io.github.hyscript7.scriptutils.modules.logging.api.LogCategory;
5+
import io.github.hyscript7.scriptutils.modules.logging.internal.services.GuildLoggingSettingsService;
6+
7+
import java.util.Arrays;
8+
import java.util.stream.Collectors;
9+
10+
public abstract class AbstractLoggingSubcommand extends Subcommand {
11+
protected final GuildLoggingSettingsService guildLoggingSettingsService;
12+
private static final String VALID_LOG_CATEGORY_NAMES = Arrays.stream(LogCategory.values())
13+
.map(LogCategory::toString)
14+
.map(s -> "`" + s + "`")
15+
.collect(Collectors.joining(", "));
16+
17+
protected AbstractLoggingSubcommand(CommandMeta meta, GuildLoggingSettingsService guildLoggingSettingsService) {
18+
super(meta);
19+
this.guildLoggingSettingsService = guildLoggingSettingsService;
20+
}
21+
22+
protected LogCategory getValidatedCategory(CommandContext context) {
23+
String category = (String) context.getOption("category");
24+
if (category == null) return null;
25+
26+
// Some people abbreviate moderation to mod, i.e. in "auto moderation", we often refer to it as "auto mod"
27+
// This performs expansion (alongside replacing spaces with underscores) so that the enum picks it up.
28+
category = category.toUpperCase().replace(' ', '_').replaceAll("(\\b)MOD(\\b)", "$1MODERATION$2");
29+
30+
try {
31+
return LogCategory.valueOf(category);
32+
} catch (IllegalArgumentException e) {
33+
context.send("# Invalid category!\nMust be one of: " + VALID_LOG_CATEGORY_NAMES +
34+
"\n\nYou can substitute `moderation` for `mod` and use any case of letters."
35+
+ "\nUnderscores can be replaced with spaces."
36+
+ "\nFor example: `AuTo MoD` is the same as `AUTO_MODERATION`.", true);
37+
return null;
38+
}
39+
}
40+
41+
protected GuildContext getValidatedGuild(CommandContext context) {
42+
return context.getGuild().orElseGet(() -> {
43+
context.send("You must be in a guild to use this command!", true);
44+
return null;
45+
});
46+
}
47+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.github.hyscript7.scriptutils.modules.logging.internal.commands;
2+
3+
import io.github.hyscript7.scriptutils.domain.discord.commands.CommandGroup;
4+
import io.github.hyscript7.scriptutils.domain.discord.commands.CommandMeta;
5+
import org.springframework.stereotype.Component;
6+
7+
@Component
8+
public class LoggingCommandGroup extends CommandGroup {
9+
public LoggingCommandGroup() {
10+
super(new CommandMeta("logging", "Commands for modifying and viewing logging configuration"));
11+
}
12+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package io.github.hyscript7.scriptutils.modules.logging.internal.commands;
2+
3+
import io.github.hyscript7.scriptutils.domain.discord.commands.CommandContext;
4+
import io.github.hyscript7.scriptutils.domain.discord.commands.CommandMeta;
5+
import io.github.hyscript7.scriptutils.domain.discord.commands.GuildContext;
6+
import io.github.hyscript7.scriptutils.domain.discord.commands.OptionMeta;
7+
import io.github.hyscript7.scriptutils.modules.logging.api.LogCategory;
8+
import io.github.hyscript7.scriptutils.modules.logging.internal.services.GuildLoggingSettingsService;
9+
import org.springframework.stereotype.Component;
10+
11+
import java.util.List;
12+
13+
@Component
14+
public class LoggingDisableSubcommand extends AbstractLoggingSubcommand {
15+
16+
public LoggingDisableSubcommand(GuildLoggingSettingsService guildLoggingSettingsService) {
17+
super(new CommandMeta("disable", "Disables a specific logging category", List.of(
18+
new OptionMeta("category", "The logging category to disable", OptionMeta.Type.STRING, true)
19+
)), guildLoggingSettingsService);
20+
}
21+
22+
@Override
23+
public void execute(CommandContext context) {
24+
GuildContext guild = getValidatedGuild(context);
25+
if (guild == null) return;
26+
27+
LogCategory logCategory = getValidatedCategory(context);
28+
if (logCategory == null) return;
29+
30+
// If category is null, it means it is disabled.
31+
guildLoggingSettingsService.setWebhookUrl(guild.getGuildId(), logCategory, null);
32+
33+
context.send("**" + logCategory.name() + "** logging has been disabled.", true);
34+
}
35+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.github.hyscript7.scriptutils.modules.logging.internal.commands;
2+
3+
import io.github.hyscript7.scriptutils.domain.discord.commands.*;
4+
import io.github.hyscript7.scriptutils.modules.logging.api.LogCategory;
5+
import io.github.hyscript7.scriptutils.modules.logging.internal.services.GuildLoggingSettingsService;
6+
import net.dv8tion.jda.api.entities.channel.Channel;
7+
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
8+
import org.springframework.stereotype.Component;
9+
10+
import java.util.List;
11+
import java.util.Optional;
12+
13+
@Component
14+
public class LoggingEnableSubcommand extends AbstractLoggingSubcommand {
15+
16+
public LoggingEnableSubcommand(GuildLoggingSettingsService guildLoggingSettingsService) {
17+
super(new CommandMeta("enable", "Enables a specific logging category", List.of(
18+
new OptionMeta("category", "The logging category to enable", OptionMeta.Type.STRING, true),
19+
new OptionMeta("channel", "The channel to log to", OptionMeta.Type.CHANNEL, true)
20+
)), guildLoggingSettingsService);
21+
}
22+
23+
@Override
24+
public void execute(CommandContext context) {
25+
GuildContext guild = getValidatedGuild(context);
26+
if (guild == null) return;
27+
28+
LogCategory logCategory = getValidatedCategory(context);
29+
if (logCategory == null) return;
30+
31+
Channel channel = (Channel) context.getOption("channel");
32+
if (!(channel instanceof TextChannel)) {
33+
context.send("Please specify a valid **text channel**!", true);
34+
return;
35+
}
36+
37+
Optional<ChannelContext> channelContext = guild.getChannel(channel.getIdLong());
38+
if (channelContext.isEmpty()) {
39+
context.send("The provided channel is inaccessible or has been deleted.", true);
40+
return;
41+
}
42+
43+
String webhookUrl = channelContext.get().createWebhook(logCategory.name() + " LOGGER");
44+
45+
guildLoggingSettingsService.setWebhookUrl(guild.getGuildId(), logCategory, webhookUrl);
46+
47+
context.send("**" + logCategory.name() + "** events will now be sent into " + channel.getAsMention() + "!\nURL: ||`" + webhookUrl + "`||", true);
48+
}
49+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package io.github.hyscript7.scriptutils.modules.logging.internal.commands;
2+
3+
import io.github.hyscript7.scriptutils.domain.discord.commands.CommandContext;
4+
import io.github.hyscript7.scriptutils.domain.discord.commands.CommandMeta;
5+
import io.github.hyscript7.scriptutils.domain.discord.commands.GuildContext;
6+
import io.github.hyscript7.scriptutils.modules.logging.internal.models.GuildLoggingSettings;
7+
import io.github.hyscript7.scriptutils.modules.logging.internal.services.GuildLoggingSettingsService;
8+
import org.springframework.stereotype.Component;
9+
10+
import java.util.List;
11+
12+
@Component
13+
public class LoggingStatusSubcommand extends AbstractLoggingSubcommand {
14+
public LoggingStatusSubcommand(GuildLoggingSettingsService guildLoggingSettingsService) {
15+
super(new CommandMeta("status", "Shows the current logging configuration for this server", List.of()),
16+
guildLoggingSettingsService);
17+
}
18+
19+
@Override
20+
public void execute(CommandContext context) {
21+
GuildContext guild = getValidatedGuild(context);
22+
if (guild == null) return;
23+
24+
GuildLoggingSettings settings = guildLoggingSettingsService.getSettingsForGuild(guild.getGuildId());
25+
26+
String sb = "# 📜 Logging Configuration\n" +
27+
"**Default**: " + getStatusEmoji(settings.getDefaultWebhookUrl()) + " \n" +
28+
"**Message**: " + getStatusEmojiForUnsupported(settings.getMessageWebhookUrl()) + " \n" +
29+
"**Member**: " + getStatusEmoji(settings.getMemberWebhookUrl()) + " \n" +
30+
"**Server**: " + getStatusEmoji(settings.getServerWebhookUrl()) + " \n" +
31+
"**Voice**: " + getStatusEmoji(settings.getVoiceWebhookUrl()) + " \n" +
32+
"**Moderation**: " + getStatusEmoji(settings.getModerationWebhookUrl()) + " \n" +
33+
"**Auto Moderation**: " + getStatusEmoji(settings.getAutoModerationWebhookUrl()) + " \n" +
34+
"\n*Use `/logging enable <category> <channel>` to activate a category.*" +
35+
"\nIf default is set, all unset categories will go to that channel.";
36+
37+
context.send(sb, true);
38+
}
39+
40+
private String getStatusEmoji(String webhookUrl) {
41+
return (webhookUrl != null && !webhookUrl.isBlank()) ? "✅ `Enabled`" : "❌ `Disabled`";
42+
}
43+
44+
private String getStatusEmojiForUnsupported(String webhookUrl) {
45+
return (webhookUrl != null && !webhookUrl.isBlank()) ? "⚠️ `Unsupported`" : "❌ `Disabled`";
46+
}
47+
}

0 commit comments

Comments
 (0)