-
-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: create role application command
Co-authored-by: Suraj Kumar <76599223+surajkumar@users.noreply.github.com>
- Loading branch information
1 parent
ee9e0e8
commit 0b18118
Showing
4 changed files
with
443 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
...rc/main/java/org/togetherjava/tjbot/features/roleapplication/ApplicationApplyHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
package org.togetherjava.tjbot.features.roleapplication; | ||
|
||
import com.github.benmanes.caffeine.cache.Cache; | ||
import com.github.benmanes.caffeine.cache.Caffeine; | ||
import net.dv8tion.jda.api.EmbedBuilder; | ||
import net.dv8tion.jda.api.entities.Guild; | ||
import net.dv8tion.jda.api.entities.Member; | ||
import net.dv8tion.jda.api.entities.MessageEmbed; | ||
import net.dv8tion.jda.api.entities.User; | ||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; | ||
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent; | ||
import net.dv8tion.jda.api.interactions.modals.ModalMapping; | ||
|
||
import org.togetherjava.tjbot.config.ApplicationFormConfig; | ||
|
||
import java.time.Duration; | ||
import java.time.Instant; | ||
import java.time.OffsetDateTime; | ||
import java.util.List; | ||
import java.util.Optional; | ||
import java.util.function.Predicate; | ||
import java.util.regex.Pattern; | ||
|
||
/** | ||
* Handles the actual process of submitting role applications. | ||
* <p> | ||
* This class is responsible for managing application submissions via modal interactions, ensuring | ||
* that submissions are sent to the appropriate application channel, and enforcing cooldowns for | ||
* users to prevent spamming. | ||
*/ | ||
public class ApplicationApplyHandler { | ||
|
||
private final Cache<Member, OffsetDateTime> applicationSubmitCooldown; | ||
private final Predicate<String> applicationChannelPattern; | ||
private final ApplicationFormConfig formConfig; | ||
|
||
/** | ||
* Constructs a new {@code ApplicationApplyHandler} instance. | ||
* | ||
* @param formConfig the configuration that contains the details for the application form | ||
* including the cooldown duration and channel pattern. | ||
*/ | ||
public ApplicationApplyHandler(ApplicationFormConfig formConfig) { | ||
this.formConfig = formConfig; | ||
this.applicationChannelPattern = | ||
Pattern.compile(formConfig.applicationChannelPattern()).asMatchPredicate(); | ||
|
||
final Duration applicationSubmitCooldownDuration = | ||
Duration.ofMinutes(formConfig.applicationSubmitCooldownMinutes()); | ||
applicationSubmitCooldown = | ||
Caffeine.newBuilder().expireAfterWrite(applicationSubmitCooldownDuration).build(); | ||
} | ||
|
||
/** | ||
* Sends the result of an application submission to the designated application channel in the | ||
* guild. | ||
* <p> | ||
* The {@code args} parameter should contain the applicant's name and the role they are applying | ||
* for. | ||
* | ||
* @param event the modal interaction event triggering the application submission | ||
* @param args the arguments provided in the application submission | ||
* @param answer the answer provided by the applicant to the default question | ||
*/ | ||
protected void sendApplicationResult(final ModalInteractionEvent event, List<String> args, | ||
String answer) { | ||
Guild guild = event.getGuild(); | ||
if (args.size() != 2 || guild == null) { | ||
return; | ||
} | ||
|
||
Optional<TextChannel> applicationChannel = getApplicationChannel(guild); | ||
if (applicationChannel.isEmpty()) { | ||
return; | ||
} | ||
|
||
User applicant = event.getUser(); | ||
EmbedBuilder embed = | ||
new EmbedBuilder().setAuthor(applicant.getName(), null, applicant.getAvatarUrl()) | ||
.setColor(ApplicationCreateCommand.AMBIENT_COLOR) | ||
.setTimestamp(Instant.now()) | ||
.setFooter("Submitted at"); | ||
|
||
String roleString = args.getLast(); | ||
MessageEmbed.Field roleField = new MessageEmbed.Field("Role", roleString, false); | ||
embed.addField(roleField); | ||
|
||
MessageEmbed.Field answerField = | ||
new MessageEmbed.Field(formConfig.defaultQuestion(), answer, false); | ||
embed.addField(answerField); | ||
|
||
applicationChannel.get().sendMessageEmbeds(embed.build()).queue(); | ||
} | ||
|
||
/** | ||
* Retrieves the application channel from the given {@link Guild}. | ||
* | ||
* @param guild the guild from which to retrieve the application channel | ||
* @return an {@link Optional} containing the {@link TextChannel} representing the application | ||
* channel, or an empty {@link Optional} if no such channel is found | ||
*/ | ||
private Optional<TextChannel> getApplicationChannel(Guild guild) { | ||
return guild.getChannels() | ||
.stream() | ||
.filter(channel -> applicationChannelPattern.test(channel.getName())) | ||
.filter(channel -> channel.getType().isMessage()) | ||
.map(TextChannel.class::cast) | ||
.findFirst(); | ||
} | ||
|
||
public Cache<Member, OffsetDateTime> getApplicationSubmitCooldown() { | ||
return applicationSubmitCooldown; | ||
} | ||
|
||
protected void submitApplicationFromModalInteraction(ModalInteractionEvent event, | ||
List<String> args) { | ||
Guild guild = event.getGuild(); | ||
|
||
if (guild == null) { | ||
return; | ||
} | ||
|
||
ModalMapping modalAnswer = event.getValues().getFirst(); | ||
|
||
sendApplicationResult(event, args, modalAnswer.getAsString()); | ||
event.reply("Your application has been submitted. Thank you for applying! 😎") | ||
.setEphemeral(true) | ||
.queue(); | ||
|
||
applicationSubmitCooldown.put(event.getMember(), OffsetDateTime.now()); | ||
} | ||
} |
Oops, something went wrong.