Skip to content

Commit 70ee0a7

Browse files
committed
staff activity
1 parent f868f2a commit 70ee0a7

File tree

5 files changed

+138
-0
lines changed

5 files changed

+138
-0
lines changed

src/main/java/net/javadiscord/javabot/data/config/guild/ModerationConfig.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ public class ModerationConfig extends GuildConfigItem {
3434
* The threshold for deleting a message in #share-knowledge. Note that this should be strictly < 0.
3535
*/
3636
private int shareKnowledgeMessageDeleteThreshold;
37+
38+
/**
39+
* ID of the channel storing staff activity information.
40+
*/
41+
private long staffActivityChannelId = 0;
3742

3843
/**
3944
* The threshold for deleting a message in #looking-for-programmer.
@@ -105,6 +110,10 @@ public ForumChannel getProjectChannel() {
105110
public ForumChannel getJobChannel() {
106111
return this.getGuild().getForumChannelById(this.jobChannelId);
107112
}
113+
114+
public TextChannel getStaffActivityChannel() {
115+
return this.getGuild().getTextChannelById(this.staffActivityChannelId);
116+
}
108117

109118
public ForumChannel getShareKnowledgeChannel() {
110119
return this.getGuild().getForumChannelById(this.shareKnowledgeChannelId);
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package net.javadiscord.javabot.systems.staff_activity;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import net.dv8tion.jda.api.EmbedBuilder;
5+
import net.dv8tion.jda.api.entities.Member;
6+
import net.dv8tion.jda.api.entities.MessageEmbed;
7+
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
8+
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
9+
import net.dv8tion.jda.api.hooks.ListenerAdapter;
10+
import net.dv8tion.jda.api.utils.TimeFormat;
11+
import net.javadiscord.javabot.data.config.BotConfig;
12+
import net.javadiscord.javabot.data.config.guild.ModerationConfig;
13+
import net.javadiscord.javabot.systems.staff_activity.dao.StaffActivityMessageRepository;
14+
import net.javadiscord.javabot.systems.staff_activity.model.StaffActivityMessage;
15+
import net.javadiscord.javabot.util.ExceptionLogger;
16+
17+
/**
18+
* Listener for tracking staff activity.
19+
* This class maintains a message for each staff member in each channel.
20+
* Each time the staff member sends a message, the message associated with the staff member is updated.
21+
*/
22+
@RequiredArgsConstructor
23+
public class StaffActivityListener extends ListenerAdapter {
24+
25+
private final BotConfig botConfig;
26+
private final StaffActivityMessageRepository repository;
27+
28+
@Override
29+
public void onMessageReceived(MessageReceivedEvent event) {
30+
if (!event.isFromGuild()) {
31+
return;
32+
}
33+
if (event.getAuthor().isBot() || event.getAuthor().isSystem()) {
34+
return;
35+
}
36+
ModerationConfig moderationConfig = botConfig.get(event.getGuild()).getModerationConfig();
37+
TextChannel staffActivityChannel = moderationConfig.getStaffActivityChannel();
38+
if (staffActivityChannel == null) {
39+
return;
40+
}
41+
Member member = event.getMember();
42+
if (!member.getRoles().contains(moderationConfig.getStaffRole())) {
43+
return;
44+
}
45+
46+
sendStaffActivityEmbed(event, staffActivityChannel, member);
47+
}
48+
49+
private void sendStaffActivityEmbed(MessageReceivedEvent event, TextChannel staffActivityChannel, Member member) {
50+
MessageEmbed embed = new EmbedBuilder()
51+
.setAuthor(member.getEffectiveName(), null, member.getEffectiveAvatarUrl())
52+
.setDescription("Last sent message: " + TimeFormat.RELATIVE.format(event.getMessage().getTimeCreated()))
53+
.setFooter(member.getId())
54+
.build();
55+
56+
Long msgId = repository.getMessageId(staffActivityChannel.getGuild().getIdLong(), member.getIdLong());
57+
if (msgId != null) {
58+
staffActivityChannel
59+
.retrieveMessageById(msgId)
60+
.queue(
61+
activityMessage -> activityMessage.editMessageEmbeds(embed).queue(),
62+
notFound -> createNewMessage(staffActivityChannel, embed, member));
63+
} else {
64+
createNewMessage(staffActivityChannel, embed, member);
65+
}
66+
}
67+
68+
private void createNewMessage(TextChannel staffActivityChannel, MessageEmbed embed, Member member) {
69+
staffActivityChannel.sendMessageEmbeds(embed).queue(success ->
70+
repository.insertOrReplace(new StaffActivityMessage(member.getGuild().getIdLong(), member.getIdLong(), success.getIdLong())),
71+
error -> ExceptionLogger.capture(error, "Cannot create new staff activity message")
72+
);
73+
}
74+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package net.javadiscord.javabot.systems.staff_activity.dao;
2+
3+
import org.springframework.jdbc.core.JdbcTemplate;
4+
import org.springframework.stereotype.Repository;
5+
6+
import lombok.RequiredArgsConstructor;
7+
import net.javadiscord.javabot.systems.staff_activity.model.StaffActivityMessage;
8+
9+
/**
10+
* Repository for storing staff activity message locations.
11+
*/
12+
@RequiredArgsConstructor
13+
@Repository
14+
public class StaffActivityMessageRepository {
15+
private final JdbcTemplate jdbcTemplate;
16+
17+
/**
18+
* Inserts a new {@link StaffActivityMessage} or replaces an old one.
19+
* @param msg the {@link StaffActivityMessage} to store
20+
*/
21+
public void insertOrReplace(StaffActivityMessage msg) {
22+
jdbcTemplate.update("""
23+
MERGE INTO staff_activity_messages
24+
(guild_id, user_id, message_id)
25+
KEY (guild_id, user_id)
26+
VALUES
27+
(?,?,?)
28+
""", msg.guildId(), msg.userId(), msg.messageId());
29+
}
30+
31+
/**
32+
* gets the ID of the activity message of a specific staff member.
33+
* @param guildId the ID of the relevant guild
34+
* @param userId the ID of the staff member
35+
* @return the message ID of the activity message
36+
*/
37+
public Long getMessageId(long guildId, long userId) {
38+
return jdbcTemplate.query("SELECT message_id FROM staff_activity_messages WHERE guild_id=? AND user_id=?", rs-> rs.next() ? (Long)rs.getLong(1) : null, guildId, userId);
39+
}
40+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package net.javadiscord.javabot.systems.staff_activity.model;
2+
3+
/**
4+
* Represents metadata of a message where activity information of a staff member is stored.
5+
* @param guildId the ID of the guild
6+
* @param userId the ID of the staff member
7+
* @param messageId the ID of the message storing activity information about the staff member
8+
*/
9+
public record StaffActivityMessage(long guildId, long userId, long messageId) {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CREATE TABLE staff_activity_messages (
2+
guild_id BIGINT NOT NULL,
3+
user_id BIGINT NOT NULL,
4+
message_id BIGINT NOT NULL,
5+
PRIMARY KEY(guild_id, user_id)
6+
)

0 commit comments

Comments
 (0)