Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/role back message #948

Merged
merged 10 commits into from
Nov 17, 2023
3 changes: 2 additions & 1 deletion application/config.json.template
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,6 @@
],
"special": [
]
}
},
"selectRolesChannelPattern": "select-your-roles"
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public final class Config {
private final JShellConfig jshell;
private final HelperPruneConfig helperPruneConfig;
private final FeatureBlacklistConfig featureBlacklistConfig;
private final String selectRolesChannelPatten;

@SuppressWarnings("ConstructorWithTooManyParameters")
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
Expand Down Expand Up @@ -82,7 +83,9 @@ private Config(@JsonProperty(value = "token", required = true) String token,
@JsonProperty(value = "helperPruneConfig",
required = true) HelperPruneConfig helperPruneConfig,
@JsonProperty(value = "featureBlacklist",
required = true) FeatureBlacklistConfig featureBlacklistConfig) {
required = true) FeatureBlacklistConfig featureBlacklistConfig,
@JsonProperty(value = "selectRolesChannelPattern",
required = true) String selectRolesChannelPatten) {
this.token = Objects.requireNonNull(token);
this.gistApiKey = Objects.requireNonNull(gistApiKey);
this.databasePath = Objects.requireNonNull(databasePath);
Expand Down Expand Up @@ -110,6 +113,7 @@ private Config(@JsonProperty(value = "token", required = true) String token,
this.jshell = Objects.requireNonNull(jshell);
this.helperPruneConfig = Objects.requireNonNull(helperPruneConfig);
this.featureBlacklistConfig = Objects.requireNonNull(featureBlacklistConfig);
this.selectRolesChannelPatten = Objects.requireNonNull(selectRolesChannelPatten);
}

/**
Expand Down Expand Up @@ -368,4 +372,8 @@ public HelperPruneConfig getHelperPruneConfig() {
public FeatureBlacklistConfig getFeatureBlacklistConfig() {
return featureBlacklistConfig;
}

public String getSelectRolesChannelPatten() {
return selectRolesChannelPatten;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -14,11 +14,15 @@
import org.togetherjava.tjbot.features.Routine;
import org.togetherjava.tjbot.features.moderation.audit.ModAuditLogWriter;

import javax.annotation.Nullable;

import java.time.Duration;
import java.time.Instant;
import java.time.Period;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.regex.Pattern;

import static org.togetherjava.tjbot.db.generated.tables.HelpChannelMessages.HELP_CHANNEL_MESSAGES;

Expand All @@ -42,6 +46,7 @@ public final class AutoPruneHelperRoutine implements Routine {
private final ModAuditLogWriter modAuditLogWriter;
private final Database database;
private final List<String> allCategories;
private final Predicate<String> selectYourRolesChannelNamePredicate;

/**
* Creates a new instance.
Expand All @@ -64,6 +69,8 @@ public AutoPruneHelperRoutine(Config config, HelpSystemHelper helper,
pruneMemberAmount = helperPruneConfig.pruneMemberAmount();
inactiveAfter = Period.ofDays(helperPruneConfig.inactivateAfterDays());
recentlyJoinedDays = helperPruneConfig.recentlyJoinedDays();
selectYourRolesChannelNamePredicate =
Pattern.compile(config.getSelectRolesChannelPatten()).asMatchPredicate();
}

@Override
Expand All @@ -77,25 +84,21 @@ public void runRoutine(JDA jda) {
}

private void pruneForGuild(Guild guild) {
ForumChannel helpForum = guild.getForumChannels()
.stream()
.filter(channel -> helper.isHelpForumName(channel.getName()))
.findAny()
.orElseThrow();
Instant now = Instant.now();
TextChannel selectRoleChannel = getSelectRolesChannelOptional(guild.getJDA()).orElse(null);

allCategories.stream()
.map(category -> helper.handleFindRoleForCategory(category, guild))
.filter(Optional::isPresent)
.map(Optional::orElseThrow)
.forEach(role -> pruneRoleIfFull(role, helpForum, now));
.forEach(role -> pruneRoleIfFull(role, selectRoleChannel, now));
}

private void pruneRoleIfFull(Role role, ForumChannel helpForum, Instant when) {
private void pruneRoleIfFull(Role role, @Nullable TextChannel selectRoleChannel, Instant when) {
role.getGuild().findMembersWithRoles(role).onSuccess(members -> {
if (isRoleFull(members)) {
logger.debug("Helper role {} is full, starting to prune.", role.getName());
pruneRole(role, members, helpForum, when);
pruneRole(role, members, selectRoleChannel, when);
}
});
}
Expand All @@ -104,8 +107,8 @@ private boolean isRoleFull(Collection<?> members) {
return members.size() >= roleFullThreshold;
}

private void pruneRole(Role role, List<? extends Member> members, ForumChannel helpForum,
Instant when) {
private void pruneRole(Role role, List<? extends Member> members,
@Nullable TextChannel selectRoleChannel, Instant when) {
List<Member> membersShuffled = new ArrayList<>(members);
Collections.shuffle(membersShuffled);

Expand All @@ -128,7 +131,7 @@ private void pruneRole(Role role, List<? extends Member> members, ForumChannel h

logger.info("Pruning {} users {} from role {}", membersToPrune.size(), membersToPrune,
role.getName());
membersToPrune.forEach(member -> pruneMemberFromRole(member, role, helpForum));
membersToPrune.forEach(member -> pruneMemberFromRole(member, role, selectRoleChannel));
}

private boolean isMemberInactive(Member member, Instant when) {
Expand All @@ -150,15 +153,20 @@ private boolean isMemberInactive(Member member, Instant when) {
.and(HELP_CHANNEL_MESSAGES.SENT_AT.greaterThan(latestActiveMoment)))) == 0;
}

private void pruneMemberFromRole(Member member, Role role, ForumChannel helpForum) {
private void pruneMemberFromRole(Member member, Role role,
@Nullable TextChannel selectRoleChannel) {
Guild guild = member.getGuild();

String channelMentionOrFallbackMessage =
selectRoleChannel == null ? "role selection channel"
: selectRoleChannel.getAsMention();

String dmMessage =
"""
You seem to have been inactive for some time in server **%s**, hence we removed you from the **%s** role.
If that was a mistake, just head back to %s and select the role again.
Sorry for any inconvenience caused by this 🙇"""
.formatted(guild.getName(), role.getName(), helpForum.getAsMention());
.formatted(guild.getName(), role.getName(), channelMentionOrFallbackMessage);

guild.removeRoleFromMember(member, role)
.flatMap(any -> member.getUser().openPrivateChannel())
Expand All @@ -173,4 +181,11 @@ private void warnModsAbout(String message, Guild guild) {

modAuditLogWriter.write("Auto-prune helpers", message, null, Instant.now(), guild);
}

private Optional<TextChannel> getSelectRolesChannelOptional(JDA jda) {
return jda.getTextChannels()
.stream()
.filter(textChannel -> selectYourRolesChannelNamePredicate.test(textChannel.getName()))
.findFirst();
}
}
Loading