mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-03-24 13:44:33 +00:00
[AB-93] changing how MessageToSend handles attached plaintext files
This commit is contained in:
@@ -7,7 +7,6 @@ import dev.sheldan.abstracto.core.command.config.Parameter;
|
|||||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
|
||||||
import dev.sheldan.abstracto.core.exception.UploadFileTooLargeException;
|
import dev.sheldan.abstracto.core.exception.UploadFileTooLargeException;
|
||||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||||
@@ -25,8 +24,6 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
@@ -46,8 +43,6 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
public class ExportEmoteStats extends AbstractConditionableCommand {
|
public class ExportEmoteStats extends AbstractConditionableCommand {
|
||||||
|
|
||||||
public static final String DOWNLOAD_EMOTE_STATS_NO_STATS_AVAILABLE_RESPONSE_TEMPLATE_KEY = "downloadEmoteStats_no_stats_available_response";
|
public static final String DOWNLOAD_EMOTE_STATS_NO_STATS_AVAILABLE_RESPONSE_TEMPLATE_KEY = "downloadEmoteStats_no_stats_available_response";
|
||||||
public static final String DOWNLOAD_EMOTE_STATS_FILE_NAME_TEMPLATE_KEY = "downloadEmoteStats_file_name";
|
|
||||||
public static final String DOWNLOAD_EMOTE_STATS_FILE_CONTENT_TEMPLATE_KEY = "downloadEmoteStats_file_content";
|
|
||||||
public static final String DOWNLOAD_EMOTE_STATS_RESPONSE_TEMPLATE_KEY = "downloadEmoteStats_response";
|
public static final String DOWNLOAD_EMOTE_STATS_RESPONSE_TEMPLATE_KEY = "downloadEmoteStats_response";
|
||||||
@Autowired
|
@Autowired
|
||||||
private ServerManagementService serverManagementService;
|
private ServerManagementService serverManagementService;
|
||||||
@@ -93,30 +88,10 @@ public class ExportEmoteStats extends AbstractConditionableCommand {
|
|||||||
.requester(commandContext.getAuthor())
|
.requester(commandContext.getAuthor())
|
||||||
.statsSince(toUseForModel)
|
.statsSince(toUseForModel)
|
||||||
.build();
|
.build();
|
||||||
String fileName = templateService.renderTemplate(DOWNLOAD_EMOTE_STATS_FILE_NAME_TEMPLATE_KEY, model);
|
MessageToSend messageToSend = templateService.renderEmbedTemplate(DOWNLOAD_EMOTE_STATS_RESPONSE_TEMPLATE_KEY, model, actualServer.getId());
|
||||||
String fileContent = templateService.renderTemplate(DOWNLOAD_EMOTE_STATS_FILE_CONTENT_TEMPLATE_KEY, model);
|
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||||
model.setEmoteStatsFileName(fileName);
|
.thenAccept(unused -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
|
||||||
File tempFile = fileService.createTempFile(fileName);
|
.thenApply(unused -> CommandResult.fromIgnored());
|
||||||
try {
|
|
||||||
fileService.writeContentToFile(tempFile, fileContent);
|
|
||||||
long maxFileSize = commandContext.getGuild().getMaxFileSize();
|
|
||||||
// in this case, we cannot upload the file, so we need to fail
|
|
||||||
if(tempFile.length() > maxFileSize) {
|
|
||||||
throw new UploadFileTooLargeException(tempFile.length(), maxFileSize);
|
|
||||||
}
|
|
||||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(DOWNLOAD_EMOTE_STATS_RESPONSE_TEMPLATE_KEY, model, actualServer.getId());
|
|
||||||
messageToSend.getAttachedFiles().get(0).setFile(tempFile.getAbsoluteFile());
|
|
||||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
|
||||||
.thenApply(unused -> CommandResult.fromIgnored());
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new AbstractoRunTimeException(e);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
fileService.safeDelete(tempFile);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Failed to delete temporary export emote statistics file {}.", tempFile.getAbsoluteFile(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package dev.sheldan.abstracto.statistic.emote.command;
|
|||||||
|
|
||||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
|
||||||
import dev.sheldan.abstracto.core.exception.UploadFileTooLargeException;
|
|
||||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||||
@@ -14,7 +12,6 @@ import dev.sheldan.abstracto.statistic.config.StatisticFeatureDefinition;
|
|||||||
import dev.sheldan.abstracto.statistic.emote.model.DownloadEmoteStatsModel;
|
import dev.sheldan.abstracto.statistic.emote.model.DownloadEmoteStatsModel;
|
||||||
import dev.sheldan.abstracto.statistic.emote.model.database.UsedEmote;
|
import dev.sheldan.abstracto.statistic.emote.model.database.UsedEmote;
|
||||||
import dev.sheldan.abstracto.statistic.emote.service.management.UsedEmoteManagementService;
|
import dev.sheldan.abstracto.statistic.emote.service.management.UsedEmoteManagementService;
|
||||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
|
||||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -22,11 +19,8 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.*;
|
import org.mockito.*;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@@ -77,53 +71,11 @@ public class ExportEmoteStatsTest {
|
|||||||
verify(channelService, times(1)).sendEmbedTemplateInTextChannelList(eq(DOWNLOAD_EMOTE_STATS_NO_STATS_AVAILABLE_RESPONSE_TEMPLATE_KEY), any(), eq(commandContext.getChannel()));
|
verify(channelService, times(1)).sendEmbedTemplateInTextChannelList(eq(DOWNLOAD_EMOTE_STATS_NO_STATS_AVAILABLE_RESPONSE_TEMPLATE_KEY), any(), eq(commandContext.getChannel()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = AbstractoRunTimeException.class)
|
|
||||||
public void testFileIOException() throws IOException {
|
|
||||||
CommandContext commandContext = CommandTestUtilities.getNoParameters();
|
|
||||||
mockServerAndFileRendering(commandContext);
|
|
||||||
File file = Mockito.mock(File.class);
|
|
||||||
when(fileService.createTempFile(FILE_NAME)).thenReturn(file);
|
|
||||||
doThrow(new IOException()).when(fileService).writeContentToFile(file, FILE_CONTENT);
|
|
||||||
testUnit.executeAsync(commandContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = UploadFileTooLargeException.class)
|
|
||||||
public void testExportAllEmoteStatsTooBig() throws IOException {
|
|
||||||
CommandContext commandContext = CommandTestUtilities.getNoParameters();
|
|
||||||
when(commandContext.getGuild().getMaxFileSize()).thenReturn(2L);
|
|
||||||
mockServerAndFileRendering(commandContext);
|
|
||||||
File file = Mockito.mock(File.class);
|
|
||||||
when(fileService.createTempFile(FILE_NAME)).thenReturn(file);
|
|
||||||
when(file.length()).thenReturn(3L);
|
|
||||||
MessageToSend messageToSend = Mockito.mock(MessageToSend.class);
|
|
||||||
CompletableFuture<CommandResult> asyncResult = testUnit.executeAsync(commandContext);
|
|
||||||
CommandTestUtilities.checkSuccessfulCompletionAsync(asyncResult);
|
|
||||||
verify(fileService, times(1)).writeContentToFile(file, FILE_CONTENT);
|
|
||||||
verify(fileService, times(1)).safeDelete(file);
|
|
||||||
verifyModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFeature() {
|
public void testFeature() {
|
||||||
Assert.assertEquals(StatisticFeatureDefinition.EMOTE_TRACKING, testUnit.getFeature());
|
Assert.assertEquals(StatisticFeatureDefinition.EMOTE_TRACKING, testUnit.getFeature());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyModel() {
|
|
||||||
DownloadEmoteStatsModel model = modelArgumentCaptor.getValue();
|
|
||||||
Assert.assertEquals(1, model.getEmotes().size());
|
|
||||||
Assert.assertEquals(usedEmote, model.getEmotes().get(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void mockServerAndFileRendering(CommandContext commandContext) {
|
|
||||||
when(commandContext.getGuild().getIdLong()).thenReturn(SERVER_ID);
|
|
||||||
AServer server = Mockito.mock(AServer.class);
|
|
||||||
when(serverManagementService.loadServer(SERVER_ID)).thenReturn(server);
|
|
||||||
List<UsedEmote> usedEmotes = Arrays.asList(usedEmote);
|
|
||||||
when(usedEmoteManagementService.loadEmoteUsagesForServerSince(server, Instant.EPOCH)).thenReturn(usedEmotes);
|
|
||||||
when(templateService.renderTemplate(eq(DOWNLOAD_EMOTE_STATS_FILE_NAME_TEMPLATE_KEY), modelArgumentCaptor.capture())).thenReturn(FILE_NAME);
|
|
||||||
when(templateService.renderTemplate(eq(DOWNLOAD_EMOTE_STATS_FILE_CONTENT_TEMPLATE_KEY), any())).thenReturn(FILE_CONTENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateCommand() {
|
public void validateCommand() {
|
||||||
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
|
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
|||||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleDefinition;
|
import dev.sheldan.abstracto.core.commands.config.ConfigModuleDefinition;
|
||||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
|
||||||
import dev.sheldan.abstracto.core.exception.CustomTemplateNotFoundException;
|
import dev.sheldan.abstracto.core.exception.CustomTemplateNotFoundException;
|
||||||
import dev.sheldan.abstracto.core.exception.UploadFileTooLargeException;
|
|
||||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||||
import dev.sheldan.abstracto.core.models.template.commands.GetCustomTemplateModel;
|
import dev.sheldan.abstracto.core.models.template.commands.GetCustomTemplateModel;
|
||||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||||
@@ -30,8 +28,6 @@ import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEve
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -67,28 +63,10 @@ public class GetCustomTemplate extends AbstractConditionableCommand {
|
|||||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||||
String templateKey = (String) commandContext.getParameters().getParameters().get(0);
|
String templateKey = (String) commandContext.getParameters().getParameters().get(0);
|
||||||
GetCustomTemplateModel model = getModel(templateKey, commandContext.getGuild());
|
GetCustomTemplateModel model = getModel(templateKey, commandContext.getGuild());
|
||||||
File tempFile = fileService.createTempFile(templateKey + ".ftl");
|
MessageToSend messageToSend = templateService.renderEmbedTemplate(GET_CUSTOM_TEMPLATE_RESPONSE_TEMPLATE_KEY, model, commandContext.getGuild().getIdLong());
|
||||||
try {
|
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||||
fileService.writeContentToFile(tempFile, model.getTemplateContent());
|
.thenAccept(interactionHook -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
|
||||||
long maxFileSize = commandContext.getGuild().getIdLong();
|
.thenApply(unused -> CommandResult.fromSuccess());
|
||||||
// in this case, we cannot upload the file, so we need to fail
|
|
||||||
if(tempFile.length() > maxFileSize) {
|
|
||||||
throw new UploadFileTooLargeException(tempFile.length(), maxFileSize);
|
|
||||||
}
|
|
||||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(GET_CUSTOM_TEMPLATE_RESPONSE_TEMPLATE_KEY, model, commandContext.getGuild().getIdLong());
|
|
||||||
messageToSend.getAttachedFiles().get(0).setFile(tempFile);
|
|
||||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInMessageChannelList(GET_CUSTOM_TEMPLATE_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
|
|
||||||
.thenApply(unused -> CommandResult.fromSuccess());
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new AbstractoRunTimeException(e);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
fileService.safeDelete(tempFile);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Failed to delete temporary get custom template file {}.", tempFile.getAbsoluteFile(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private GetCustomTemplateModel getModel(String templateKey, Guild guild) {
|
private GetCustomTemplateModel getModel(String templateKey, Guild guild) {
|
||||||
@@ -109,27 +87,10 @@ public class GetCustomTemplate extends AbstractConditionableCommand {
|
|||||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||||
String templateKey = slashCommandParameterService.getCommandOption(TEMPLATE_KEY_PARAMETER, event, String.class);
|
String templateKey = slashCommandParameterService.getCommandOption(TEMPLATE_KEY_PARAMETER, event, String.class);
|
||||||
GetCustomTemplateModel model = getModel(templateKey, event.getGuild());
|
GetCustomTemplateModel model = getModel(templateKey, event.getGuild());
|
||||||
File tempFile = fileService.createTempFile(templateKey + ".ftl");
|
MessageToSend messageToSend = templateService.renderEmbedTemplate(GET_CUSTOM_TEMPLATE_RESPONSE_TEMPLATE_KEY, model, event.getGuild().getIdLong());
|
||||||
try {
|
return interactionService.replyMessageToSend(messageToSend, event)
|
||||||
fileService.writeContentToFile(tempFile, model.getTemplateContent());
|
.thenAccept(interactionHook -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
|
||||||
long maxFileSize = event.getGuild().getMaxFileSize();
|
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||||
// in this case, we cannot upload the file, so we need to fail
|
|
||||||
if(tempFile.length() > maxFileSize) {
|
|
||||||
throw new UploadFileTooLargeException(tempFile.length(), maxFileSize);
|
|
||||||
}
|
|
||||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(GET_CUSTOM_TEMPLATE_RESPONSE_TEMPLATE_KEY, model, event.getGuild().getIdLong());
|
|
||||||
messageToSend.getAttachedFiles().get(0).setFile(tempFile);
|
|
||||||
return interactionService.replyMessageToSend(messageToSend, event)
|
|
||||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new AbstractoRunTimeException(e);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
fileService.safeDelete(tempFile);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Failed to delete temporary get custom template file {}.", tempFile.getAbsoluteFile(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
|||||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleDefinition;
|
import dev.sheldan.abstracto.core.commands.config.ConfigModuleDefinition;
|
||||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
|
||||||
import dev.sheldan.abstracto.core.exception.TemplateNotFoundException;
|
import dev.sheldan.abstracto.core.exception.TemplateNotFoundException;
|
||||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||||
import dev.sheldan.abstracto.core.models.template.commands.GetTemplateModel;
|
import dev.sheldan.abstracto.core.models.template.commands.GetTemplateModel;
|
||||||
@@ -27,8 +26,6 @@ import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEve
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
@@ -63,44 +60,20 @@ public class GetTemplate extends AbstractConditionableCommand {
|
|||||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||||
String templateKey = (String) commandContext.getParameters().getParameters().get(0);
|
String templateKey = (String) commandContext.getParameters().getParameters().get(0);
|
||||||
GetTemplateModel model = getModel(templateKey);
|
GetTemplateModel model = getModel(templateKey);
|
||||||
File tempFile = fileService.createTempFile(templateKey + ".ftl");
|
|
||||||
try {
|
|
||||||
fileService.writeContentToFile(tempFile, model.getTemplateContent());
|
|
||||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(GET_TEMPLATE_RESPONSE_TEMPLATE_KEY, model, commandContext.getGuild().getIdLong());
|
MessageToSend messageToSend = templateService.renderEmbedTemplate(GET_TEMPLATE_RESPONSE_TEMPLATE_KEY, model, commandContext.getGuild().getIdLong());
|
||||||
messageToSend.getAttachedFiles().get(0).setFile(tempFile);
|
|
||||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||||
|
.thenAccept(interactionHook -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
|
||||||
.thenApply(unused -> CommandResult.fromSuccess());
|
.thenApply(unused -> CommandResult.fromSuccess());
|
||||||
} catch (IOException e) {
|
|
||||||
throw new AbstractoRunTimeException(e);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
fileService.safeDelete(tempFile);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Failed to delete temporary get template file {}.", tempFile.getAbsoluteFile(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||||
String templateKey = slashCommandParameterService.getCommandOption(TEMPLATE_KEY_PARAMETER, event, String.class);
|
String templateKey = slashCommandParameterService.getCommandOption(TEMPLATE_KEY_PARAMETER, event, String.class);
|
||||||
GetTemplateModel model = getModel(templateKey);
|
GetTemplateModel model = getModel(templateKey);
|
||||||
File tempFile = fileService.createTempFile(templateKey + ".ftl");
|
|
||||||
try {
|
|
||||||
fileService.writeContentToFile(tempFile, model.getTemplateContent());
|
|
||||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(GET_TEMPLATE_RESPONSE_TEMPLATE_KEY, model, event.getGuild().getIdLong());
|
MessageToSend messageToSend = templateService.renderEmbedTemplate(GET_TEMPLATE_RESPONSE_TEMPLATE_KEY, model, event.getGuild().getIdLong());
|
||||||
messageToSend.getAttachedFiles().get(0).setFile(tempFile);
|
|
||||||
return interactionService.replyMessageToSend(messageToSend, event)
|
return interactionService.replyMessageToSend(messageToSend, event)
|
||||||
|
.thenAccept(interactionHook -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
|
||||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||||
} catch (IOException e) {
|
|
||||||
throw new AbstractoRunTimeException(e);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
fileService.safeDelete(tempFile);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Failed to delete temporary get template file {}.", tempFile.getAbsoluteFile(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private GetTemplateModel getModel(String templateKey) {
|
private GetTemplateModel getModel(String templateKey) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
|||||||
import dev.sheldan.abstracto.core.templating.model.AttachedFile;
|
import dev.sheldan.abstracto.core.templating.model.AttachedFile;
|
||||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||||
|
import dev.sheldan.abstracto.core.utils.FileService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||||
@@ -57,6 +58,9 @@ public class InteractionServiceBean implements InteractionService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private TemplateService templateService;
|
private TemplateService templateService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private FileService fileService;
|
||||||
|
|
||||||
public static final CounterMetric EPHEMERAL_MESSAGES_SEND = CounterMetric
|
public static final CounterMetric EPHEMERAL_MESSAGES_SEND = CounterMetric
|
||||||
.builder()
|
.builder()
|
||||||
.name(DISCORD_API_INTERACTION_METRIC)
|
.name(DISCORD_API_INTERACTION_METRIC)
|
||||||
|
|||||||
@@ -199,6 +199,16 @@ public class ChannelServiceBean implements ChannelService {
|
|||||||
if(messageToSend.getEphemeral()) {
|
if(messageToSend.getEphemeral()) {
|
||||||
throw new IllegalArgumentException("Ephemeral messages are only supported in interaction context.");
|
throw new IllegalArgumentException("Ephemeral messages are only supported in interaction context.");
|
||||||
}
|
}
|
||||||
|
if(textChannel instanceof GuildMessageChannel) {
|
||||||
|
GuildMessageChannel guildMessageChannel = (GuildMessageChannel) textChannel;
|
||||||
|
long maxFileSize = guildMessageChannel.getGuild().getMaxFileSize();
|
||||||
|
// in this case, we cannot upload the file, so we need to fail
|
||||||
|
messageToSend.getAttachedFiles().forEach(attachedFile -> {
|
||||||
|
if(attachedFile.getFile().length() > maxFileSize) {
|
||||||
|
throw new UploadFileTooLargeException(attachedFile.getFile().length(), maxFileSize);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
List<CompletableFuture<Message>> futures = new ArrayList<>();
|
List<CompletableFuture<Message>> futures = new ArrayList<>();
|
||||||
List<MessageCreateAction> allMessageActions = new ArrayList<>();
|
List<MessageCreateAction> allMessageActions = new ArrayList<>();
|
||||||
Iterator<MessageEmbed> embedIterator = messageToSend.getEmbeds().iterator();
|
Iterator<MessageEmbed> embedIterator = messageToSend.getEmbeds().iterator();
|
||||||
@@ -332,6 +342,14 @@ public class ChannelServiceBean implements ChannelService {
|
|||||||
throw new IllegalArgumentException("Message to send did not contain anything to send.");
|
throw new IllegalArgumentException("Message to send did not contain anything to send.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(messageToSend.getAttachedFiles() != null && !messageToSend.getAttachedFiles().isEmpty()) {
|
||||||
|
List<FileUpload> files = messageToSend
|
||||||
|
.getAttachedFiles()
|
||||||
|
.stream()
|
||||||
|
.map(AttachedFile::convertToFileUpload)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
messageAction = messageAction.setFiles(files);
|
||||||
|
}
|
||||||
messageAction = messageAction.setComponents(messageToSend.getActionRows());
|
messageAction = messageAction.setComponents(messageToSend.getActionRows());
|
||||||
metricService.incrementCounter(MESSAGE_EDIT_METRIC);
|
metricService.incrementCounter(MESSAGE_EDIT_METRIC);
|
||||||
return messageAction.submit();
|
return messageAction.submit();
|
||||||
|
|||||||
@@ -10,4 +10,6 @@ import lombok.Setter;
|
|||||||
public class FileConfig {
|
public class FileConfig {
|
||||||
private String fileName;
|
private String fileName;
|
||||||
private Boolean spoiler;
|
private Boolean spoiler;
|
||||||
|
// only used for plaintext files
|
||||||
|
private String fileContent;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import dev.sheldan.abstracto.core.service.ConfigService;
|
|||||||
import dev.sheldan.abstracto.core.templating.Templatable;
|
import dev.sheldan.abstracto.core.templating.Templatable;
|
||||||
import dev.sheldan.abstracto.core.templating.exception.TemplatingException;
|
import dev.sheldan.abstracto.core.templating.exception.TemplatingException;
|
||||||
import dev.sheldan.abstracto.core.templating.model.*;
|
import dev.sheldan.abstracto.core.templating.model.*;
|
||||||
|
import dev.sheldan.abstracto.core.utils.FileService;
|
||||||
import freemarker.template.Configuration;
|
import freemarker.template.Configuration;
|
||||||
import freemarker.template.Template;
|
import freemarker.template.Template;
|
||||||
import freemarker.template.TemplateException;
|
import freemarker.template.TemplateException;
|
||||||
@@ -28,6 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
@@ -56,6 +58,9 @@ public class TemplateServiceBean implements TemplateService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ConfigService configService;
|
private ConfigService configService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private FileService fileService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats the passed passed count with the embed used for formatting pages.
|
* Formats the passed passed count with the embed used for formatting pages.
|
||||||
*
|
*
|
||||||
@@ -172,11 +177,22 @@ public class TemplateServiceBean implements TemplateService {
|
|||||||
List<AttachedFile> files = new ArrayList<>();
|
List<AttachedFile> files = new ArrayList<>();
|
||||||
if(messageConfiguration.getFiles() != null && !messageConfiguration.getFiles().isEmpty()) {
|
if(messageConfiguration.getFiles() != null && !messageConfiguration.getFiles().isEmpty()) {
|
||||||
messageConfiguration.getFiles().forEach(fileToAttach -> {
|
messageConfiguration.getFiles().forEach(fileToAttach -> {
|
||||||
|
String fileName = fileToAttach.getFileName() != null ? fileToAttach.getFileName() : RandomStringUtils.randomAlphabetic(5);
|
||||||
AttachedFile attachedFile = AttachedFile
|
AttachedFile attachedFile = AttachedFile
|
||||||
.builder()
|
.builder()
|
||||||
.fileName(fileToAttach.getFileName() != null ? fileToAttach.getFileName() : RandomStringUtils.randomAlphabetic(5))
|
.fileName(fileName)
|
||||||
.spoiler(fileToAttach.getSpoiler())
|
.spoiler(fileToAttach.getSpoiler() != null && fileToAttach.getSpoiler())
|
||||||
.build();
|
.build();
|
||||||
|
if(fileToAttach.getFileContent() != null) {
|
||||||
|
File tempFile = fileService.createTempFile(fileName);
|
||||||
|
try {
|
||||||
|
fileService.writeContentToFile(tempFile, fileToAttach.getFileContent());
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Failed to write local temporary file.", e);
|
||||||
|
throw new AbstractoRunTimeException(e);
|
||||||
|
}
|
||||||
|
attachedFile.setFile(tempFile);
|
||||||
|
}
|
||||||
files.add(attachedFile);
|
files.add(attachedFile);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,4 +36,12 @@ public class FileService {
|
|||||||
public void safeDelete(File file) throws IOException {
|
public void safeDelete(File file) throws IOException {
|
||||||
java.nio.file.Files.delete(file.toPath());
|
java.nio.file.Files.delete(file.toPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void safeDeleteIgnoreException(File file) {
|
||||||
|
try {
|
||||||
|
Files.delete(file.toPath());
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("Failed to delete file - ignoring.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user