Skip to content

Commit 5002f75

Browse files
committed
Analytics: remove AnalyticsService injection in PingCommand and using it from BotCore;
1 parent 8774945 commit 5002f75

File tree

6 files changed

+45
-51
lines changed

6 files changed

+45
-51
lines changed

application/src/main/java/org/togetherjava/tjbot/features/Features.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import org.togetherjava.tjbot.config.FeatureBlacklist;
77
import org.togetherjava.tjbot.config.FeatureBlacklistConfig;
88
import org.togetherjava.tjbot.db.Database;
9-
import org.togetherjava.tjbot.features.analytics.AnalyticsService;
109
import org.togetherjava.tjbot.features.basic.MemberCountDisplayRoutine;
1110
import org.togetherjava.tjbot.features.basic.PingCommand;
1211
import org.togetherjava.tjbot.features.basic.QuoteBoardForwarder;
@@ -129,7 +128,6 @@ public static Collection<Feature> createFeatures(JDA jda, Database database, Con
129128
TopHelpersService topHelpersService = new TopHelpersService(database);
130129
TopHelpersAssignmentRoutine topHelpersAssignmentRoutine =
131130
new TopHelpersAssignmentRoutine(config, topHelpersService);
132-
AnalyticsService analyticsService = new AnalyticsService(database);
133131

134132
// NOTE The system can add special system relevant commands also by itself,
135133
// hence this list may not necessarily represent the full list of all commands actually
@@ -186,7 +184,7 @@ public static Collection<Feature> createFeatures(JDA jda, Database database, Con
186184

187185
// Slash commands
188186
features.add(new LogLevelCommand());
189-
features.add(new PingCommand(analyticsService));
187+
features.add(new PingCommand());
190188
features.add(new TeXCommand());
191189
features.add(new TagCommand(tagSystem));
192190
features.add(new TagManageCommand(tagSystem, modAuditLogWriter));

application/src/main/java/org/togetherjava/tjbot/features/analytics/AnalyticsService.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,49 +36,49 @@ public AnalyticsService(Database database) {
3636
* This method should be called by commands after they complete execution to track usage
3737
* patterns and error rates.
3838
*
39-
* @param guildId the guild ID where the command was executed
39+
* @param channelId the channel ID where the command was executed
4040
* @param commandName the name of the command that was executed
4141
* @param userId the ID of the user who executed the command
4242
* @param success whether the command executed successfully
4343
* @param errorMessage optional error message if the command failed (null if successful)
4444
*/
45-
public void recordCommandExecution(long guildId, String commandName, long userId,
45+
public void recordCommandExecution(long channelId, String commandName, long userId,
4646
boolean success, @Nullable String errorMessage) {
4747

4848
database.write(context -> context
49-
.insertInto(DSL.table("command_usage"), DSL.field("guild_id"),
49+
.insertInto(DSL.table("command_usage"), DSL.field("channel_id"),
5050
DSL.field("command_name"), DSL.field("user_id"), DSL.field("executed_at"),
5151
DSL.field("success"), DSL.field("error_message"))
52-
.values(guildId, commandName, userId, DSL.currentTimestamp(), success, errorMessage)
52+
.values(channelId, commandName, userId, DSL.currentTimestamp(), success, errorMessage)
5353
.execute());
5454

5555
if (!success && errorMessage != null) {
56-
logger.warn("Command '{}' failed in guild {} with error: {}", commandName, guildId,
56+
logger.warn("Command '{}' failed on channel {} with error: {}", commandName, channelId,
5757
errorMessage);
5858
}
5959
}
6060

6161
/**
6262
* Records a successful command execution.
6363
*
64-
* @param guildId the guild ID where the command was executed
64+
* @param channelId the channel ID where the command was executed
6565
* @param commandName the name of the command that was executed
6666
* @param userId the ID of the user who executed the command
6767
*/
68-
public void recordCommandSuccess(long guildId, String commandName, long userId) {
69-
recordCommandExecution(guildId, commandName, userId, true, null);
68+
public void recordCommandSuccess(long channelId, String commandName, long userId) {
69+
recordCommandExecution(channelId, commandName, userId, true, null);
7070
}
7171

7272
/**
7373
* Records a failed command execution.
7474
*
75-
* @param guildId the guild ID where the command was executed
75+
* @param channelId the channel ID where the command was executed
7676
* @param commandName the name of the command that was executed
7777
* @param userId the ID of the user who executed the command
7878
* @param errorMessage a description of what went wrong
7979
*/
80-
public void recordCommandFailure(long guildId, String commandName, long userId,
80+
public void recordCommandFailure(long channelId, String commandName, long userId,
8181
String errorMessage) {
82-
recordCommandExecution(guildId, commandName, userId, false, errorMessage);
82+
recordCommandExecution(channelId, commandName, userId, false, errorMessage);
8383
}
8484
}

application/src/main/java/org/togetherjava/tjbot/features/basic/PingCommand.java

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,19 @@
55

66
import org.togetherjava.tjbot.features.CommandVisibility;
77
import org.togetherjava.tjbot.features.SlashCommandAdapter;
8-
import org.togetherjava.tjbot.features.analytics.AnalyticsService;
98

109
/**
1110
* Implementation of an example command to illustrate how to respond to a user.
1211
* <p>
1312
* The implemented command is {@code /ping}, upon which the bot will respond with {@code Pong!}.
1413
*/
1514
public final class PingCommand extends SlashCommandAdapter {
16-
private final AnalyticsService analyticsService;
1715

1816
/**
1917
* Creates an instance of the ping pong command.
20-
*
21-
* @param analyticsService the analytics service to track command usage
2218
*/
23-
public PingCommand(AnalyticsService analyticsService) {
19+
public PingCommand() {
2420
super("ping", "Bot responds with 'Pong!'", CommandVisibility.GUILD);
25-
this.analyticsService = analyticsService;
2621
}
2722

2823
/**
@@ -38,17 +33,6 @@ public void onSlashCommand(SlashCommandInteractionEvent event) {
3833
return;
3934
}
4035

41-
try {
42-
event.reply("Pong!").queue();
43-
44-
analyticsService.recordCommandSuccess(guild.getIdLong(), getName(),
45-
event.getUser().getIdLong());
46-
47-
} catch (Exception e) {
48-
analyticsService.recordCommandFailure(guild.getIdLong(), getName(),
49-
event.getUser().getIdLong(),
50-
e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName());
51-
throw e;
52-
}
36+
event.reply("Pong!").queue();
5337
}
5438
}

application/src/main/java/org/togetherjava/tjbot/features/system/BotCore.java

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import net.dv8tion.jda.api.hooks.ListenerAdapter;
2424
import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback;
2525
import net.dv8tion.jda.api.interactions.components.ComponentInteraction;
26-
import org.jetbrains.annotations.NotNull;
2726
import org.jetbrains.annotations.Nullable;
2827
import org.jetbrains.annotations.Unmodifiable;
2928
import org.slf4j.Logger;
@@ -42,6 +41,7 @@
4241
import org.togetherjava.tjbot.features.UserInteractionType;
4342
import org.togetherjava.tjbot.features.UserInteractor;
4443
import org.togetherjava.tjbot.features.VoiceReceiver;
44+
import org.togetherjava.tjbot.features.analytics.AnalyticsService;
4545
import org.togetherjava.tjbot.features.componentids.ComponentId;
4646
import org.togetherjava.tjbot.features.componentids.ComponentIdParser;
4747
import org.togetherjava.tjbot.features.componentids.ComponentIdStore;
@@ -79,13 +79,13 @@ public final class BotCore extends ListenerAdapter implements CommandProvider {
7979
private static final ExecutorService COMMAND_SERVICE = Executors.newCachedThreadPool();
8080
private static final ScheduledExecutorService ROUTINE_SERVICE =
8181
Executors.newScheduledThreadPool(5);
82-
private final Config config;
8382
private final Map<String, UserInteractor> prefixedNameToInteractor;
8483
private final List<Routine> routines;
8584
private final ComponentIdParser componentIdParser;
8685
private final ComponentIdStore componentIdStore;
8786
private final Map<Pattern, MessageReceiver> channelNameToMessageReceiver = new HashMap<>();
8887
private final Map<Pattern, VoiceReceiver> channelNameToVoiceReceiver = new HashMap<>();
88+
private final AnalyticsService analyticsService;
8989

9090
/**
9191
* Creates a new command system which uses the given database to allow commands to persist data.
@@ -97,9 +97,11 @@ public final class BotCore extends ListenerAdapter implements CommandProvider {
9797
* @param config the configuration to use for this system
9898
*/
9999
public BotCore(JDA jda, Database database, Config config) {
100-
this.config = config;
101100
Collection<Feature> features = Features.createFeatures(jda, database, config);
102101

102+
// Initialize analytics service
103+
analyticsService = new AnalyticsService(database);
104+
103105
// Message receivers
104106
features.stream()
105107
.filter(MessageReceiver.class::isInstance)
@@ -300,14 +302,14 @@ private Optional<Channel> selectPreferredAudioChannel(@Nullable AudioChannelUnio
300302
}
301303

302304
@Override
303-
public void onGuildVoiceUpdate(@NotNull GuildVoiceUpdateEvent event) {
305+
public void onGuildVoiceUpdate(GuildVoiceUpdateEvent event) {
304306
selectPreferredAudioChannel(event.getChannelJoined(), event.getChannelLeft())
305307
.ifPresent(channel -> getVoiceReceiversSubscribedTo(channel)
306308
.forEach(voiceReceiver -> voiceReceiver.onVoiceUpdate(event)));
307309
}
308310

309311
@Override
310-
public void onGuildVoiceVideo(@NotNull GuildVoiceVideoEvent event) {
312+
public void onGuildVoiceVideo(GuildVoiceVideoEvent event) {
311313
AudioChannelUnion channel = event.getVoiceState().getChannel();
312314

313315
if (channel == null) {
@@ -319,7 +321,7 @@ public void onGuildVoiceVideo(@NotNull GuildVoiceVideoEvent event) {
319321
}
320322

321323
@Override
322-
public void onGuildVoiceStream(@NotNull GuildVoiceStreamEvent event) {
324+
public void onGuildVoiceStream(GuildVoiceStreamEvent event) {
323325
AudioChannelUnion channel = event.getVoiceState().getChannel();
324326

325327
if (channel == null) {
@@ -331,7 +333,7 @@ public void onGuildVoiceStream(@NotNull GuildVoiceStreamEvent event) {
331333
}
332334

333335
@Override
334-
public void onGuildVoiceMute(@NotNull GuildVoiceMuteEvent event) {
336+
public void onGuildVoiceMute(GuildVoiceMuteEvent event) {
335337
AudioChannelUnion channel = event.getVoiceState().getChannel();
336338

337339
if (channel == null) {
@@ -343,7 +345,7 @@ public void onGuildVoiceMute(@NotNull GuildVoiceMuteEvent event) {
343345
}
344346

345347
@Override
346-
public void onGuildVoiceDeafen(@NotNull GuildVoiceDeafenEvent event) {
348+
public void onGuildVoiceDeafen(GuildVoiceDeafenEvent event) {
347349
AudioChannelUnion channel = event.getVoiceState().getChannel();
348350

349351
if (channel == null) {
@@ -380,10 +382,24 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
380382

381383
logger.debug("Received slash command '{}' (#{}) on guild '{}'", name, event.getId(),
382384
event.getGuild());
383-
COMMAND_SERVICE.execute(
384-
() -> requireUserInteractor(UserInteractionType.SLASH_COMMAND.getPrefixedName(name),
385+
COMMAND_SERVICE.execute(() -> {
386+
try {
387+
requireUserInteractor(UserInteractionType.SLASH_COMMAND.getPrefixedName(name),
385388
SlashCommand.class)
386-
.onSlashCommand(event));
389+
.onSlashCommand(event);
390+
391+
392+
analyticsService.recordCommandSuccess(event.getChannel().getIdLong(), name,
393+
event.getUser().getIdLong());
394+
} catch (Exception ex) {
395+
396+
analyticsService.recordCommandFailure(event.getChannel().getIdLong(), name,
397+
event.getUser().getIdLong(),
398+
ex.getMessage() != null ? ex.getMessage() : ex.getClass().getSimpleName());
399+
400+
throw ex;
401+
}
402+
});
387403
}
388404

389405
@Override
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
CREATE TABLE command_usage
22
(
33
id INTEGER PRIMARY KEY AUTOINCREMENT,
4-
guild_id INTEGER NOT NULL,
4+
channel_id INTEGER NOT NULL,
55
command_name TEXT NOT NULL,
66
user_id INTEGER NOT NULL,
7-
executed_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
7+
executed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
88
success BOOLEAN NOT NULL DEFAULT TRUE,
99
error_message TEXT
1010
);
1111

12-
CREATE INDEX idx_command_usage_guild ON command_usage(guild_id);
12+
CREATE INDEX idx_command_usage_channel ON command_usage(channel_id);
1313
CREATE INDEX idx_command_usage_command_name ON command_usage(command_name);

application/src/test/java/org/togetherjava/tjbot/features/basic/PingCommandTest.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,13 @@
66
import org.junit.jupiter.api.Test;
77

88
import org.togetherjava.tjbot.features.SlashCommand;
9-
import org.togetherjava.tjbot.features.analytics.AnalyticsService;
109
import org.togetherjava.tjbot.jda.JdaTester;
1110

12-
import static org.mockito.Mockito.mock;
1311
import static org.mockito.Mockito.verify;
1412

1513
final class PingCommandTest {
1614
private JdaTester jdaTester;
1715
private SlashCommand command;
18-
private AnalyticsService analyticsService;
1916

2017
private SlashCommandInteractionEvent triggerSlashCommand() {
2118
SlashCommandInteractionEvent event =
@@ -27,8 +24,7 @@ private SlashCommandInteractionEvent triggerSlashCommand() {
2724
@BeforeEach
2825
void setUp() {
2926
jdaTester = new JdaTester();
30-
analyticsService = mock(AnalyticsService.class);
31-
command = jdaTester.spySlashCommand(new PingCommand(analyticsService));
27+
command = jdaTester.spySlashCommand(new PingCommand());
3228
}
3329

3430
@Test

0 commit comments

Comments
 (0)