added mod mail thread notification, if a user initiates a mod mail thread

added the concept of a mod mail role, these are roles being pinged when a thread is opened, and they also are able to execute mod mail related commands
fixed past thread count in mod mail header
added convenience method to allow a role to execute a whole feature
This commit is contained in:
Sheldan
2020-05-08 10:49:06 +02:00
parent ea6fe240f4
commit 7699075b33
27 changed files with 289 additions and 20 deletions

View File

@@ -60,7 +60,7 @@ public class Contact extends AbstractConditionableCommand {
.aUserInAServer(user)
.member(targetUser)
.build();
modMailThreadService.createModMailThreadForUser(fullUser, commandContext.getChannel());
modMailThreadService.createModMailThreadForUser(fullUser, commandContext.getChannel(), false);
}
return CommandResult.fromSuccess();
}

View File

@@ -0,0 +1,53 @@
package dev.sheldan.abstracto.modmail.commands;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.modmail.config.ModMailFeatures;
import dev.sheldan.abstracto.modmail.service.ModMailRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class SetModMailRole extends AbstractConditionableCommand {
@Autowired
private ModMailRoleService modMailRoleService;
@Override
public CommandResult execute(CommandContext commandContext) {
ARole role = (ARole) commandContext.getParameters().getParameters().get(0);
modMailRoleService.addRoleToModMailRoles(role, commandContext.getUserInitiatedContext().getServer());
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter categoryId = Parameter.builder().name("role").type(ARole.class).description("The role to be notified by new mod mail threads").build();
List<Parameter> parameters = Arrays.asList(categoryId);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
List<String> aliases = Arrays.asList("modMailRole");
return CommandConfiguration.builder()
.name("setModMailRole")
.module(ModMailModuleInterface.MODMAIL)
.aliases(aliases)
.parameters(parameters)
.help(helpInfo)
.templated(true)
.causesReaction(true)
.build();
}
@Override
public FeatureEnum getFeature() {
return ModMailFeatures.MODMAIL;
}
}

View File

@@ -0,0 +1,16 @@
package dev.sheldan.abstracto.modmail.repository;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.modmail.models.database.ModMailRole;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ModMailRoleRepository extends JpaRepository<ModMailRole, Long> {
boolean existsByServerAndRole(AServer server, ARole role);
List<ModMailRole> findByServer(AServer server);
}

View File

@@ -0,0 +1,31 @@
package dev.sheldan.abstracto.modmail.service;
import dev.sheldan.abstracto.core.command.service.CommandService;
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.modmail.config.ModMailFeatures;
import dev.sheldan.abstracto.modmail.service.management.ModMailRoleManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class ModMailRoleServiceBean implements ModMailRoleService {
@Autowired
private ModMailRoleManagementService modMailRoleManagementService;
@Autowired
private CommandService commandService;
@Autowired
private FeatureManagementService featureManagementService;
@Override
public void addRoleToModMailRoles(ARole role, AServer server) {
if(!modMailRoleManagementService.isRoleAlreadyAssigned(role, server)) {
modMailRoleManagementService.addRoleToModMailRoles(role, server);
}
commandService.allowFeatureForRole(ModMailFeatures.MODMAIL, role);
}
}

View File

@@ -11,11 +11,13 @@ import dev.sheldan.abstracto.core.service.management.UserInServerManagementServi
import dev.sheldan.abstracto.core.service.management.UserInServerService;
import dev.sheldan.abstracto.modmail.config.ModMailFeature;
import dev.sheldan.abstracto.modmail.models.database.ModMailMessage;
import dev.sheldan.abstracto.modmail.models.database.ModMailRole;
import dev.sheldan.abstracto.modmail.models.database.ModMailThread;
import dev.sheldan.abstracto.modmail.models.database.ModMailThreadState;
import dev.sheldan.abstracto.modmail.models.dto.ServerChoice;
import dev.sheldan.abstracto.modmail.models.template.*;
import dev.sheldan.abstracto.modmail.service.management.ModMailMessageManagementService;
import dev.sheldan.abstracto.modmail.service.management.ModMailRoleManagementService;
import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.templating.service.TemplateService;
@@ -79,6 +81,9 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
@Autowired
private ModMailFeature modMailFeature;
@Autowired
private ModMailRoleManagementService modMailRoleManagementService;
@Autowired
private ModMailThreadServiceBean self;
@@ -89,13 +94,13 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
@Override
public void createModMailThreadForUser(FullUser aUserInAServer, MessageChannel feedBackChannel) {
public void createModMailThreadForUser(FullUser aUserInAServer, MessageChannel feedBackChannel, Boolean userInitiated) {
Long categoryId = configService.getLongValue(MODMAIL_CATEGORY, aUserInAServer.getAUserInAServer().getServerReference().getId());
User user = aUserInAServer.getMember().getUser();
CompletableFuture<TextChannel> textChannel = channelService.createTextChannel(user.getName() + user.getDiscriminator(), aUserInAServer.getAUserInAServer().getServerReference(), categoryId);
textChannel.thenAccept(channel -> {
self.performModMailThreadSetup(aUserInAServer, channel);
self.performModMailThreadSetup(aUserInAServer, channel, userInitiated);
}).exceptionally(throwable -> {
log.error("Failed to create mod mail thread", throwable);
sendModMailFailure("modmail_exception_failed_to_create_mod_mail_thread", aUserInAServer.getAUserInAServer(), null, feedBackChannel, throwable);
@@ -104,15 +109,30 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
}
@Transactional
public void performModMailThreadSetup(FullUser aUserInAServer, TextChannel channel) {
createThreadObject(channel, aUserInAServer);
public void performModMailThreadSetup(FullUser aUserInAServer, TextChannel channel, Boolean userInitiated) {
ModMailThread thread = createThreadObject(channel, aUserInAServer);
sendModMailHeader(channel, aUserInAServer);
if(userInitiated) {
sendModMailNotification(aUserInAServer, thread);
}
}
public void createThreadObject(TextChannel channel, FullUser user) {
private void sendModMailNotification(FullUser aUserInAServer, ModMailThread thread) {
List<ModMailRole> rolesToPing = modMailRoleManagementService.getRolesForServer(thread.getServer());
ModMailNotificationModel modMailNotificationModel = ModMailNotificationModel
.builder()
.modMailThread(thread)
.threadUser(aUserInAServer)
.roles(rolesToPing)
.build();
MessageToSend messageToSend = templateService.renderEmbedTemplate("modmail_notification_message", modMailNotificationModel);
postTargetService.sendEmbedInPostTarget(messageToSend, "modmailping", thread.getServer().getId());
}
public ModMailThread createThreadObject(TextChannel channel, FullUser user) {
AChannel channel2 = channelManagementService.createChannel(channel.getIdLong(), AChannelType.TEXT, user.getAUserInAServer().getServerReference());
log.info("Creating mod mail thread in channel {} with db channel {}", channel.getIdLong(), channel2.getId());
modMailThreadManagementService.createModMailThread(user.getAUserInAServer(), channel2);
return modMailThreadManagementService.createModMailThread(user.getAUserInAServer(), channel2);
}
@Override
@@ -168,7 +188,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
AUserInAServer chosenServer = choices.get(reactionEmote.getEmoji());
Member memberInServer = botService.getMemberInServer(chosenServer);
FullUser fullUser = FullUser.builder().member(memberInServer).aUserInAServer(chosenServer).build();
self.createModMailThreadForUser(fullUser, channel);
self.createModMailThreadForUser(fullUser, channel, true);
botService.getInstance().removeEventListener(waiter);
})
.build();
@@ -188,7 +208,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
.builder()
.threadUser(aUserInAServer)
.latestModMailThread(latestThread)
.pastModMailThreads((long)oldThreads.size())
.pastModMailThreadCount((long)oldThreads.size())
.build();
channelService.sendTemplateInChannel("modmail_thread_header", header, channel);
}

View File

@@ -0,0 +1,37 @@
package dev.sheldan.abstracto.modmail.service.management;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.modmail.models.database.ModMailRole;
import dev.sheldan.abstracto.modmail.repository.ModMailRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ModMailRoleManagementServiceBean implements ModMailRoleManagementService {
@Autowired
private ModMailRoleRepository modMailRoleRepository;
@Override
public void addRoleToModMailRoles(ARole role, AServer server) {
ModMailRole roleToAdd = ModMailRole
.builder()
.role(role)
.server(server)
.build();
modMailRoleRepository.save(roleToAdd);
}
@Override
public List<ModMailRole> getRolesForServer(AServer server) {
return modMailRoleRepository.findByServer(server);
}
@Override
public boolean isRoleAlreadyAssigned(ARole role, AServer server) {
return modMailRoleRepository.existsByServerAndRole(server, role);
}
}

View File

@@ -64,7 +64,7 @@ public class ModMailThreadManagementServiceBean implements ModMailThreadManageme
}
@Override
public void createModMailThread(AUserInAServer userInAServer, AChannel channel) {
public ModMailThread createModMailThread(AUserInAServer userInAServer, AChannel channel) {
ModMailThread thread = ModMailThread
.builder()
.channel(channel)
@@ -76,6 +76,7 @@ public class ModMailThreadManagementServiceBean implements ModMailThreadManageme
.build();
modMailThreadRepository.save(thread);
return thread;
}
@Override

View File

@@ -1,3 +1,3 @@
abstracto.postTargets.modmail=modmaillog
abstracto.postTargets.modmail=modmaillog,modmailping
abstracto.emoteNames.readReaction=readReaction
abstracto.defaultEmotes.readReaction=\uD83D\uDC40

View File

@@ -0,0 +1,19 @@
{
"author": {
"name": "${threadUser.member.effectiveName}",
"avatar": "${threadUser.member.user.effectiveAvatarUrl}"
},
"title": {
"title": "<#include "modmail_notification_message_title">"
},
"color" : {
"r": 200,
"g": 0,
"b": 255
},
<#assign user>${threadUser.member.effectiveName}#${threadUser.member.user.discriminator}(${threadUser.member.user.id})</#assign>
"description": "<#include "modmail_notification_message_description">"
<#if roles?size gt 0>
,"additionalMessage": "<#list roles as role>${role.role.asMention}<#sep>,</#list>"
</#if>
}

View File

@@ -11,6 +11,5 @@
<#assign user>${threadUser.member.effectiveName}#${threadUser.member.user.discriminator} (${threadUser.member.user.id})</#assign>
<#assign joinDate>${threadUser.member.timeJoined}</#assign>
<#assign roles><#list threadUser.member.roles as role>${role.asMention}<#sep>,<#else>No roles</#list></#assign>
<#assign threadCount>3</#assign>
"description": "<#include "modmail_thread_header_embed_description">"
}

View File

@@ -0,0 +1,32 @@
package dev.sheldan.abstracto.modmail.models.database;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import lombok.*;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
@Builder
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "modmail_roles")
@Cacheable
@Getter
@Setter
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class ModMailRole {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long modMailRoleId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "modmail_role_server", nullable = false)
private AServer server;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "modmail_role", nullable = false)
private ARole role;
}

View File

@@ -0,0 +1,20 @@
package dev.sheldan.abstracto.modmail.models.template;
import dev.sheldan.abstracto.core.models.FullUser;
import dev.sheldan.abstracto.core.models.context.ServerContext;
import dev.sheldan.abstracto.modmail.models.database.ModMailRole;
import dev.sheldan.abstracto.modmail.models.database.ModMailThread;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import java.util.List;
@Getter
@Setter
@SuperBuilder
public class ModMailNotificationModel extends ServerContext {
private ModMailThread modMailThread;
private FullUser threadUser;
private List<ModMailRole> roles;
}

View File

@@ -12,5 +12,5 @@ import lombok.Setter;
public class ModMailThreaderHeader {
private FullUser threadUser;
private ModMailThread latestModMailThread;
private Long pastModMailThreads;
private Long pastModMailThreadCount;
}

View File

@@ -0,0 +1,8 @@
package dev.sheldan.abstracto.modmail.service;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
public interface ModMailRoleService {
void addRoleToModMailRoles(ARole role, AServer server);
}

View File

@@ -10,7 +10,7 @@ import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageChannel;
public interface ModMailThreadService {
void createModMailThreadForUser(FullUser userInAServer, MessageChannel feedBackChannel);
void createModMailThreadForUser(FullUser userInAServer, MessageChannel feedBackChannel, Boolean userInitiated);
boolean hasOpenThread(AUserInAServer aUserInAServer);
boolean hasOpenThread(AUser user);
void setModMailCategoryTo(AServer server, Long categoryId);

View File

@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.modmail.service.management;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.modmail.models.database.ModMailRole;
import java.util.List;
public interface ModMailRoleManagementService {
void addRoleToModMailRoles(ARole role, AServer server);
List<ModMailRole> getRolesForServer(AServer server);
boolean isRoleAlreadyAssigned(ARole role, AServer server);
}

View File

@@ -17,7 +17,7 @@ public interface ModMailThreadManagementService {
ModMailThread getOpenModmailThreadForUser(AUser user);
List<ModMailThread> getModMailThreadForUser(AUserInAServer aUserInAServer);
ModMailThread getLatestModMailThread(AUserInAServer aUserInAServer);
void createModMailThread(AUserInAServer userInAServer, AChannel channel);
ModMailThread createModMailThread(AUserInAServer userInAServer, AChannel channel);
void setModMailThreadState(ModMailThread modMailThread, ModMailThreadState newState);
}