Skip to content

Commit fdd7bce

Browse files
squashed everything(kinda)
1 parent a018539 commit fdd7bce

File tree

9 files changed

+200
-67
lines changed

9 files changed

+200
-67
lines changed

application/config.json.template

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,23 @@
9696
"baseUrl": "<put_jshell_rest_api_url_here>",
9797
"rateLimitWindowSeconds": 10,
9898
"rateLimitRequestsInWindow": 3
99+
},
100+
"helperPruneConfig": {
101+
"roleFullLimit": 100,
102+
"roleFullThreshold": 95,
103+
"pruneMemberAmount": 7,
104+
"inactivateAfterDays": 90,
105+
"recentlyJoinedDays": 4
106+
},
107+
"featureBlacklist": {
108+
"normal": [
109+
],
110+
"special": [
111+
]
99112
}
100-
"oofsAndLmaos": {
101-
"oofEmojiName": ":oof:"
102-
"lmaoEmojiName": ":lmao"
103-
"starboardChannelId": <put_channel_id_here>
113+
"starboard": {
114+
"emojiNames" : ["star"],
115+
"channelPattern": "starboard"
104116
}
105117
},
106118
"featureBlacklist": {

application/src/main/java/org/togetherjava/tjbot/config/Config.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,12 @@ public final class Config {
4242
private final String openaiApiKey;
4343
private final String sourceCodeBaseUrl;
4444
private final JShellConfig jshell;
45+
private final StarboardConfig starboard;
4546
private final FeatureBlacklistConfig featureBlacklistConfig;
4647
private final RSSFeedsConfig rssFeedsConfig;
4748
private final String selectRolesChannelPattern;
4849
private final String memberCountCategoryPattern;
49-
private final OofsAndLmaosConfig oofsAndLmaos;
50+
5051

5152
@SuppressWarnings("ConstructorWithTooManyParameters")
5253
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
@@ -96,7 +97,7 @@ private Config(@JsonProperty(value = "token", required = true) String token,
9697
@JsonProperty(value = "rssConfig", required = true) RSSFeedsConfig rssFeedsConfig,
9798
@JsonProperty(value = "selectRolesChannelPattern",
9899
required = true) String selectRolesChannelPattern,
99-
@JsonProperty(value = "oofsAndLmaos", required = true) OofsAndLmaosConfig oofsAndLmaos) {
100+
@JsonProperty(value = "starboard", required = true) StarboardConfig starboard) {
100101
this.token = Objects.requireNonNull(token);
101102
this.githubApiKey = Objects.requireNonNull(githubApiKey);
102103
this.databasePath = Objects.requireNonNull(databasePath);
@@ -129,7 +130,7 @@ private Config(@JsonProperty(value = "token", required = true) String token,
129130
this.featureBlacklistConfig = Objects.requireNonNull(featureBlacklistConfig);
130131
this.rssFeedsConfig = Objects.requireNonNull(rssFeedsConfig);
131132
this.selectRolesChannelPattern = Objects.requireNonNull(selectRolesChannelPattern);
132-
this.oofsAndLmaos = Objects.requireNonNull(oofsAndLmaos);
133+
this.starboard = Objects.requireNonNull(starboard);
133134
}
134135

135136
/**
@@ -383,9 +384,6 @@ public String getSourceCodeBaseUrl() {
383384
*/
384385
public JShellConfig getJshell() {
385386
return jshell;
386-
}
387-
public OofsAndLmaosConfig getOofsAndLmaos() {
388-
return oofsAndLmaos;
389387
}
390388

391389
/**
@@ -397,6 +395,17 @@ public FeatureBlacklistConfig getFeatureBlacklistConfig() {
397395
return featureBlacklistConfig;
398396
}
399397

398+
/**
399+
* Gets the config for the Starboard. The starboard displays certain messages in a special
400+
* emojis{@link StarboardConfig#emojiNames()}
401+
* channel {@link StarboardConfig#channelPattern()} if a user reacts with one of the recognized
402+
*
403+
* @return the config of the Starboard
404+
*/
405+
public StarboardConfig getStarboard() {
406+
return starboard;
407+
}
408+
400409
/**
401410
* Gets the REGEX pattern used to identify the channel in which users can select their helper
402411
* roles.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.togetherjava.tjbot.config;
2+
3+
4+
/**
5+
* Config for automatic pruning of helper roles, see
6+
* {@link org.togetherjava.tjbot.features.help.AutoPruneHelperRoutine}.
7+
*
8+
* @param roleFullLimit if a helper role contains that many users, it is considered full and pruning
9+
* must occur
10+
* @param roleFullThreshold if a helper role contains that many users, pruning will start to occur
11+
* to prevent reaching the limit
12+
* @param pruneMemberAmount amount of users to remove from helper roles during a prune
13+
* @param inactivateAfterDays after how many days of inactivity a user is eligible for pruning
14+
* @param recentlyJoinedDays if a user is with the server for just this amount of days, they are
15+
* protected from pruning
16+
*/
17+
public record HelperPruneConfig(int roleFullLimit, int roleFullThreshold, int pruneMemberAmount,
18+
int inactivateAfterDays, int recentlyJoinedDays) {
19+
}

application/src/main/java/org/togetherjava/tjbot/config/OofsAndLmaosConfig.java

Lines changed: 0 additions & 30 deletions
This file was deleted.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package org.togetherjava.tjbot.config;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonRootName;
5+
6+
import java.util.List;
7+
import java.util.Objects;
8+
import java.util.regex.Pattern;
9+
10+
/**
11+
* Starboard Config
12+
*
13+
* @param emojiNames the List of emojis which are recognized by the starboard
14+
* @param channelPattern the pattern of the channel with the starboard
15+
*/
16+
@JsonRootName("starboard")
17+
public record StarboardConfig(List<String> emojiNames, Pattern channelPattern) {
18+
/**
19+
* Creates a Starboard config.
20+
*
21+
* @param emojiNames the List of emojis which are recognized by the starboard
22+
* @param channelPattern the pattern of the channel with the starboard
23+
*/
24+
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
25+
public StarboardConfig {
26+
Objects.requireNonNull(emojiNames);
27+
Objects.requireNonNull(channelPattern);
28+
}
29+
30+
/**
31+
* Gets the list of emotes that are recognized by the starboard feature. A message that is
32+
* reacted on with an emote in this list will be reposted in a special channel
33+
* {@link #channelPattern()}.
34+
* <p>
35+
* Empty to deactivate the feature.
36+
*
37+
* @return The List of emojis recognized by the starboard
38+
*/
39+
@Override
40+
public List<String> emojiNames() {
41+
return emojiNames;
42+
}
43+
44+
/**
45+
* Gets the pattern of the channel with the starboard. Deactivate by using a non-existent
46+
* channel name.
47+
*
48+
* @return the pattern of the channel with the starboard
49+
*/
50+
public Pattern channelPattern() {
51+
return channelPattern;
52+
}
53+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.togetherjava.tjbot.features.basic.PingCommand;
1111
import org.togetherjava.tjbot.features.basic.RoleSelectCommand;
1212
import org.togetherjava.tjbot.features.basic.SlashCommandEducator;
13+
import org.togetherjava.tjbot.features.basic.Starboard;
1314
import org.togetherjava.tjbot.features.basic.SuggestionsUpDownVoter;
1415
import org.togetherjava.tjbot.features.bookmarks.BookmarksCommand;
1516
import org.togetherjava.tjbot.features.bookmarks.BookmarksSystem;
@@ -131,6 +132,7 @@ public static Collection<Feature> createFeatures(JDA jda, Database database, Con
131132
features.add(new GuildLeaveCloseThreadListener(config));
132133
features.add(new LeftoverBookmarksListener(bookmarksSystem));
133134
features.add(new HelpThreadCreatedListener(helpSystemHelper));
135+
features.add(new Starboard(config, database));
134136

135137
// Message context commands
136138
features.add(new TransferQuestionCommand(config));

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

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package org.togetherjava.tjbot.features.basic;
2+
3+
import com.github.benmanes.caffeine.cache.Cache;
4+
import com.github.benmanes.caffeine.cache.Caffeine;
5+
import net.dv8tion.jda.api.EmbedBuilder;
6+
import net.dv8tion.jda.api.Permission;
7+
import net.dv8tion.jda.api.entities.Guild;
8+
import net.dv8tion.jda.api.entities.Message;
9+
import net.dv8tion.jda.api.entities.MessageEmbed;
10+
import net.dv8tion.jda.api.entities.User;
11+
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
12+
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
13+
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
14+
import net.dv8tion.jda.api.hooks.ListenerAdapter;
15+
import org.jetbrains.annotations.NotNull;
16+
import org.slf4j.Logger;
17+
import org.slf4j.LoggerFactory;
18+
19+
import org.togetherjava.tjbot.config.Config;
20+
import org.togetherjava.tjbot.config.StarboardConfig;
21+
import org.togetherjava.tjbot.db.Database;
22+
import org.togetherjava.tjbot.features.EventReceiver;
23+
24+
import java.util.Optional;
25+
import java.util.concurrent.TimeUnit;
26+
27+
import static org.togetherjava.tjbot.db.generated.tables.StarboardMessages.STARBOARD_MESSAGES;
28+
29+
public class Starboard extends ListenerAdapter implements EventReceiver {
30+
31+
private static final Logger logger = LoggerFactory.getLogger(Starboard.class);
32+
private final StarboardConfig config;
33+
private final Database database;
34+
35+
private final Cache<Long, Object> messageCache;
36+
37+
public Starboard(Config config, Database database) {
38+
this.config = config.getStarboard();
39+
this.database = database;
40+
this.messageCache = Caffeine.newBuilder()
41+
.maximumSize(100)
42+
.expireAfterAccess(24, TimeUnit.HOURS) // TODO make these constants
43+
.build();
44+
}
45+
46+
@Override
47+
public void onMessageReactionAdd(@NotNull MessageReactionAddEvent event) {
48+
String emojiName = event.getEmoji().asCustom().getName();
49+
Guild guild = event.getGuild();
50+
long messageId = event.getMessageIdLong();
51+
if (shouldIgnoreMessage(emojiName, guild, event.getGuildChannel(), messageId)) {
52+
return;
53+
}
54+
Optional<TextChannel> starboardChannel = getStarboardChannel(guild);
55+
if (starboardChannel.isEmpty()) {
56+
logger.warn("There is no channel for the starboard in the guild with the name {}",
57+
config.channelPattern());
58+
return;
59+
}
60+
database.write(context -> context.newRecord(STARBOARD_MESSAGES).setMessageId(messageId));
61+
messageCache.put(messageId, new Object());
62+
event.retrieveMessage()
63+
.flatMap(
64+
message -> starboardChannel.orElseThrow().sendMessageEmbeds(formEmbed(message)))
65+
.queue();
66+
}
67+
68+
private boolean shouldIgnoreMessage(String emojiName, Guild guild, GuildChannel channel,
69+
long messageId) {
70+
return !config.emojiNames().contains(emojiName)
71+
|| !guild.getPublicRole().hasPermission(channel, Permission.VIEW_CHANNEL)
72+
|| messageCache.getIfPresent(messageId) != null
73+
|| database
74+
.read(context -> context.fetchExists(context.selectFrom(STARBOARD_MESSAGES)
75+
.where(STARBOARD_MESSAGES.MESSAGE_ID.eq(messageId))));
76+
}
77+
78+
private Optional<TextChannel> getStarboardChannel(Guild guild) {
79+
return guild.getTextChannels()
80+
.stream()
81+
.filter(channel -> config.channelPattern().matcher(channel.getName()).find())
82+
.findFirst();
83+
}
84+
85+
private static MessageEmbed formEmbed(Message message) {
86+
User author = message.getAuthor();
87+
return new EmbedBuilder().setAuthor(author.getName(), null, author.getAvatarUrl())
88+
.setDescription(message.getContentDisplay())
89+
.build(); // TODO make footer with link and reacted emojis
90+
}
91+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CREATE TABLE starboard_messages
2+
(
3+
message_id BIGINT NOT NULL PRIMARY KEY
4+
)

0 commit comments

Comments
 (0)