mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-20 23:08:02 +00:00
Compare commits
17 Commits
abstracto-
...
abstracto-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd70e6ac90 | ||
|
|
29bde70796 | ||
|
|
ecd4feabb2 | ||
|
|
abf60409f1 | ||
|
|
080733957f | ||
|
|
8a41f366ae | ||
|
|
dbf478c44c | ||
|
|
3df688571f | ||
|
|
ca530949c6 | ||
|
|
724930e5a4 | ||
|
|
2875da117a | ||
|
|
f95ba6c28f | ||
|
|
1b2e7654f9 | ||
|
|
54976ed1d4 | ||
|
|
735816f5dd | ||
|
|
a984bdb84e | ||
|
|
21add6585d |
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Sheldan
|
||||
Copyright (c) 2023 Sheldan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
10
README.md
10
README.md
@@ -14,22 +14,20 @@ An example implementation of this bot can be seen [here](https://github.com/Shel
|
||||
|
||||
|
||||
## Technologies
|
||||
* [JDA](https://github.com/DV8FromTheWorld/JDA/) The Discord API Wrapper in the version 5.0.0-alpha.21
|
||||
* [Spring boot](https://github.com/spring-projects/spring-boot) is used as a framework to create standalone application in Java with Java EE methods. (including Dependency injection and more)
|
||||
* [JDA](https://github.com/DV8FromTheWorld/JDA/) The Discord API Wrapper in the version 5.0.0-beta.5
|
||||
* [Spring boot](https://github.com/spring-projects/spring-boot) is used as a framework to create standalone application in Java with Java EE methods. (including dependency injection and more)
|
||||
* [Hibernate](https://github.com/hibernate/hibernate-orm) is used as a reference implementation of JPA.
|
||||
* [Freemarker](https://github.com/apache/freemarker) is used as a templating engine. This is used to provide internationalization for user facing text and enable dynamic embed configuration.
|
||||
* [Ehcache](https://github.com/ehcache/ehcache3) is used as a caching implementation.
|
||||
* [Lombok](https://github.com/rzwitserloot/lombok) is used as a framework in order to speed up creation of container classes and builders.
|
||||
* [Quartz](https://github.com/quartz-scheduler/quartz) is used as a scheduling framework in order to provide functionalities which either require a delayed or cronjob behaviour.
|
||||
* [Docker](https://github.com/docker) is used to package the application into a container and [Docker Compose](https://github.com/docker/compose) is used to connect the required containers together.
|
||||
* [Quartz](https://github.com/quartz-scheduler/quartz) is used as a scheduling framework in order to provide functionalities which either require a scheduled or cronjob behaviour.
|
||||
* [Docker](https://github.com/docker) is used to package the application into an image and [Docker Compose](https://github.com/docker/compose) is used to build the images
|
||||
* [Liquibase](https://github.com/liquibase/liquibase) is used to manage changes to the database
|
||||
|
||||
## Documentation
|
||||
A detailed documentation of the pure form of Abstracto including the terminology and commands in HTML form is available [here](https://sheldan.github.io/abstracto-docs/current). The PDF is available [here](https://sheldan.github.io/abstracto-docs/current/documentation.pdf)
|
||||
If you want to view the documentation to an earlier released version you need to append the desired version to the URL. The current version will be available aforementioned URL, but it is not right now, because Abstracto has not been released yet.
|
||||
|
||||
## Customization documentation
|
||||
TBD when Abstracto is released, as the current version is still being adapted, because of findings from the example customization in Crimson.
|
||||
|
||||
## Issues
|
||||
If you find any issue, feel free to create a GitHub issue.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>assignable-roles-int</artifactId>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>custom-command</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>custom-command</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>dynamic-activity</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>dynamic-activity</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -275,13 +275,13 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
CompletableFuture<Void> returningFuture;
|
||||
if(!Objects.equals(oldRoleId, newRoleId) || forceRoles) {
|
||||
CompletableFuture<Void> addingFuture;
|
||||
if(oldRoleId != null || forceRoles) {
|
||||
if(oldRoleId != null) {
|
||||
addingFuture = roleService.removeRoleFromMemberAsync(member, oldRoleId);
|
||||
} else {
|
||||
addingFuture = CompletableFuture.completedFuture(null);
|
||||
}
|
||||
CompletableFuture<Void> removingFeature;
|
||||
if(newRoleId != null || forceRoles) {
|
||||
if(newRoleId != null) {
|
||||
removingFeature = roleService.addRoleToMemberAsync(member, newRoleId);
|
||||
} else {
|
||||
removingFeature = CompletableFuture.completedFuture(null);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>invite-filter</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>invite-filter</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>link-embed</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>link-embed</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>logging</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>logging</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>modmail</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberNameDisplay;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
@@ -81,6 +82,7 @@ public class Contact extends AbstractConditionableCommand {
|
||||
ModMailThreadExistsModel model = ModMailThreadExistsModel
|
||||
.builder()
|
||||
.existingModMailThread(existingThread)
|
||||
.executingMemberDisplay(MemberNameDisplay.fromMember(commandContext.getAuthor()))
|
||||
.build();
|
||||
List<CompletableFuture<Message>> futures = channelService.sendEmbedTemplateInTextChannelList(MODMAIL_THREAD_ALREADY_EXISTS_TEMPLATE, model, commandContext.getChannel());
|
||||
return FutureUtils.toSingleFutureGeneric(futures).thenApply(aVoid -> CommandResult.fromIgnored());
|
||||
@@ -106,6 +108,7 @@ public class Contact extends AbstractConditionableCommand {
|
||||
ModMailThreadExistsModel model = ModMailThreadExistsModel
|
||||
.builder()
|
||||
.existingModMailThread(existingThread)
|
||||
.executingMemberDisplay(MemberNameDisplay.fromMember(event.getMember()))
|
||||
.build();
|
||||
return interactionService.replyEmbed(MODMAIL_THREAD_ALREADY_EXISTS_TEMPLATE, model, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>modmail</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.sheldan.abstracto.modmail.model.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberNameDisplay;
|
||||
import dev.sheldan.abstracto.core.utils.ChannelUtils;
|
||||
import dev.sheldan.abstracto.modmail.model.database.ModMailThread;
|
||||
import lombok.Builder;
|
||||
@@ -15,6 +16,7 @@ import lombok.Setter;
|
||||
@Builder
|
||||
public class ModMailThreadExistsModel {
|
||||
private ModMailThread existingModMailThread;
|
||||
private MemberNameDisplay executingMemberDisplay;
|
||||
|
||||
public String getThreadUrl() {
|
||||
return ChannelUtils.buildChannelUrl(existingModMailThread.getServer().getId(), existingModMailThread.getChannel().getId());
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto</groupId>
|
||||
<artifactId>abstracto-application</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>profanity-filter</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>profanity-filter</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>remind</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -249,6 +249,7 @@ public class RemindServiceBeanTest {
|
||||
when(guild.getIdLong()).thenReturn(8L);
|
||||
when(remindedMember.getIdLong()).thenReturn(9L);
|
||||
when(remindedMember.getUser()).thenReturn(jdaUser);
|
||||
when(remindedMember.getEffectiveAvatar()).thenReturn(Mockito.mock(ImageProxy.class));
|
||||
when(jdaUser.getDefaultAvatar()).thenReturn(Mockito.mock(ImageProxy.class));
|
||||
Reminder remindedReminder = Mockito.mock(Reminder.class);
|
||||
when(remindedReminder.getTargetDate()).thenReturn(Instant.now());
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>remind</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>repost-detection</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>repost-detection</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>starboard</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>starboard</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>statistic</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -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.CommandResult;
|
||||
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.models.database.AServer;
|
||||
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.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
@@ -46,8 +43,6 @@ import java.util.concurrent.CompletableFuture;
|
||||
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_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";
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
@@ -93,30 +88,10 @@ public class ExportEmoteStats extends AbstractConditionableCommand {
|
||||
.requester(commandContext.getAuthor())
|
||||
.statsSince(toUseForModel)
|
||||
.build();
|
||||
String fileName = templateService.renderTemplate(DOWNLOAD_EMOTE_STATS_FILE_NAME_TEMPLATE_KEY, model);
|
||||
String fileContent = templateService.renderTemplate(DOWNLOAD_EMOTE_STATS_FILE_CONTENT_TEMPLATE_KEY, model);
|
||||
model.setEmoteStatsFileName(fileName);
|
||||
File tempFile = fileService.createTempFile(fileName);
|
||||
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);
|
||||
}
|
||||
}
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(DOWNLOAD_EMOTE_STATS_RESPONSE_TEMPLATE_KEY, model, actualServer.getId());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenAccept(unused -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
@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.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.service.ChannelService;
|
||||
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.database.UsedEmote;
|
||||
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 org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
@@ -22,11 +19,8 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
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()));
|
||||
}
|
||||
|
||||
@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
|
||||
public void testFeature() {
|
||||
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
|
||||
public void validateCommand() {
|
||||
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>statistic</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>suggestion</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>suggestion</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>utility</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>utility</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>voice-channel-context</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>voice-channel-context</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>webservices</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package dev.sheldan.abstracto.webservices.openeweathermap.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
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.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.webservices.config.WebServicesSlashCommandNames;
|
||||
import dev.sheldan.abstracto.webservices.config.WebserviceFeatureDefinition;
|
||||
import dev.sheldan.abstracto.webservices.openweathermap.config.OpenWeatherMapConfig;
|
||||
import dev.sheldan.abstracto.webservices.openweathermap.exception.LocationNotFoundException;
|
||||
import dev.sheldan.abstracto.webservices.openweathermap.model.*;
|
||||
import dev.sheldan.abstracto.webservices.openweathermap.service.OpenWeatherMapService;
|
||||
import dev.sheldan.abstracto.webservices.openweathermap.service.WeatherService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.checkerframework.checker.index.qual.SameLen;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class OpenWeatherMap extends AbstractConditionableCommand {
|
||||
|
||||
private static final String OPEN_WEATHER_MAP_COMMAND = "openWeatherMap";
|
||||
private static final String SEARCH_QUERY_PARAMETER = "searchQuery";
|
||||
private static final String OPEN_WEATHER_MAP_RESPONSE_TEMPLATE_KEY = "openWeatherMap_command_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private OpenWeatherMapService openWeatherMapService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private WeatherService weatherService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
String parameter = (String) commandContext.getParameters().getParameters().get(0);
|
||||
MessageToSend message = getMessageToSend(commandContext.getGuild().getIdLong(), parameter);
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(message, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String query = slashCommandParameterService.getCommandOption(SEARCH_QUERY_PARAMETER, event, String.class);
|
||||
MessageToSend messageToSend = getMessageToSend(event.getGuild().getIdLong(), query);
|
||||
return interactionService.replyMessageToSend(messageToSend, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
private MessageToSend getMessageToSend(Long serverId, String parameter) {
|
||||
try {
|
||||
GeoCodingResult geoCodingResult = openWeatherMapService.searchForLocation(parameter);
|
||||
if(geoCodingResult.getResults().isEmpty()) {
|
||||
throw new LocationNotFoundException();
|
||||
}
|
||||
String languageKey = configService.getStringValueOrConfigDefault(OpenWeatherMapConfig.OPEN_WEATHER_MAP_LANGUAGE_KEY_SYSTEM_CONFIG_KEY, serverId);
|
||||
GeoCodingLocation chosenLocation = geoCodingResult.getResults().get(0);
|
||||
WeatherResult weatherResult = openWeatherMapService.retrieveWeatherForLocation(chosenLocation, languageKey);
|
||||
WeatherResponseModel.WeatherResponseModelBuilder builder = WeatherResponseModel
|
||||
.builder()
|
||||
.description(weatherResult.getWeathers() != null && !weatherResult.getWeathers().isEmpty()
|
||||
? weatherResult.getWeathers().get(0).getDescription() : null)
|
||||
.mainWeather(weatherResult.getWeathers() != null && !weatherResult.getWeathers().isEmpty()
|
||||
? weatherResult.getWeathers().get(0).getMain() : null)
|
||||
.clouds(weatherResult.getCloudInfo() != null ? weatherResult.getCloudInfo().getAll() : null)
|
||||
.rain1H(weatherResult.getRainInfo() != null ? weatherResult.getRainInfo().getRain1H() : null)
|
||||
.rain3H(weatherResult.getRainInfo() != null ? weatherResult.getRainInfo().getRain3H() : null)
|
||||
.snow1H(weatherResult.getSnowInfo() != null ? weatherResult.getSnowInfo().getSnow1H() : null)
|
||||
.snow3H(weatherResult.getSnowInfo() != null ? weatherResult.getSnowInfo().getSnow3H() : null)
|
||||
.visibility(weatherResult.getVisibility())
|
||||
.locationName(chosenLocation.getName())
|
||||
.countryKey(chosenLocation.getCountryKey())
|
||||
.dataCalculationTime(weatherResult.getDayTime() != null ? Instant.ofEpochSecond(weatherResult.getDayTime()) : null);
|
||||
Color embedColor = null;
|
||||
WeatherResultMain mainWeather = weatherResult.getMainWeather();
|
||||
if(mainWeather != null) {
|
||||
builder.feelsLikeTemperature(mainWeather.getFeelsLikeTemperature())
|
||||
.temperature(mainWeather.getTemperature())
|
||||
.maxTemperature(mainWeather.getMaxTemperature())
|
||||
.minTemperature(mainWeather.getMinTemperature())
|
||||
.pressure(mainWeather.getPressure())
|
||||
.seaLevelPressure(mainWeather.getSeaLevelPressure())
|
||||
.groundLevelPressure(mainWeather.getGroundLevelPressure())
|
||||
.humidity(mainWeather.getHumidity());
|
||||
embedColor = weatherService.getColorForTemperature(mainWeather.getFeelsLikeTemperature());
|
||||
}
|
||||
builder.embedColor(embedColor);
|
||||
WeatherResultSystem systemInfo = weatherResult.getSystemInfo();
|
||||
if(systemInfo != null) {
|
||||
builder.sunset(systemInfo.getSunset() != null ? Instant.ofEpochSecond(systemInfo.getSunset()) : null);
|
||||
builder.sunset(systemInfo.getSunrise() != null ? Instant.ofEpochSecond(systemInfo.getSunrise()) : null);
|
||||
}
|
||||
builder.locationId(weatherResult.getLocationId());
|
||||
return templateService.renderEmbedTemplate(OPEN_WEATHER_MAP_RESPONSE_TEMPLATE_KEY, builder.build(), serverId);
|
||||
} catch (IOException e) {
|
||||
log.warn("Failed to load weather in server {}", serverId, e);
|
||||
throw new AbstractoRunTimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return WebserviceFeatureDefinition.OPEN_WEATHER_MAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
Parameter searchQueryParameter = Parameter
|
||||
.builder()
|
||||
.name(SEARCH_QUERY_PARAMETER)
|
||||
.type(String.class)
|
||||
.remainder(true)
|
||||
.templated(true)
|
||||
.build();
|
||||
parameters.add(searchQueryParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(WebServicesSlashCommandNames.WEATHER)
|
||||
.commandName("search")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(OPEN_WEATHER_MAP_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package dev.sheldan.abstracto.webservices.openeweathermap.service;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import dev.sheldan.abstracto.webservices.openweathermap.model.GeoCodingLocation;
|
||||
import dev.sheldan.abstracto.webservices.openweathermap.model.GeoCodingResult;
|
||||
import dev.sheldan.abstracto.webservices.openweathermap.model.WeatherResult;
|
||||
import dev.sheldan.abstracto.webservices.openweathermap.service.OpenWeatherMapService;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class OpenWeatherMapServiceBean implements OpenWeatherMapService {
|
||||
|
||||
@Autowired
|
||||
private OkHttpClient okHttpClient;
|
||||
|
||||
@Value("${abstracto.feature.webservices.openweatherMap.apiKey}")
|
||||
private String apiKey;
|
||||
|
||||
@Value("${abstracto.feature.webservices.openweathermap.geocodingURL}")
|
||||
private String geoCodingURL;
|
||||
|
||||
@Value("${abstracto.feature.webservices.openweathermap.weatherDataURL}")
|
||||
private String weatherDataURL;
|
||||
|
||||
@Autowired
|
||||
private Gson gson;
|
||||
|
||||
@Override
|
||||
public GeoCodingResult searchForLocation(String query) throws IOException {
|
||||
Type geoCodingType = new TypeToken<ArrayList<GeoCodingLocation>>() {}.getType();
|
||||
Request request = new Request.Builder()
|
||||
.url(String.format(geoCodingURL, query, 5, apiKey))
|
||||
.get()
|
||||
.build();
|
||||
Response response = okHttpClient.newCall(request).execute();
|
||||
List<GeoCodingLocation> result = gson.fromJson(response.body().string(), geoCodingType);
|
||||
return GeoCodingResult
|
||||
.builder()
|
||||
.results(result)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeatherResult retrieveWeatherForLocation(GeoCodingLocation location, String languageKey) throws IOException {
|
||||
Request request = new Request.Builder()
|
||||
.url(String.format(weatherDataURL, location.getLatitude(), location.getLongitude(), apiKey, languageKey))
|
||||
.get()
|
||||
.build();
|
||||
Response response = okHttpClient.newCall(request).execute();
|
||||
return gson.fromJson(response.body().string(), WeatherResult.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package dev.sheldan.abstracto.webservices.openeweathermap.service;
|
||||
|
||||
import dev.sheldan.abstracto.webservices.openweathermap.service.WeatherService;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class WeatherServiceBean implements WeatherService {
|
||||
|
||||
private static final Map<Pair<Integer, Integer>, String> TEMPERATURE_COLOR_MAP = new HashMap<>();
|
||||
|
||||
// source for colors: https://www.esri.com/arcgis-blog/products/arcgis-pro/mapping/a-meaningful-temperature-palette/
|
||||
static {
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-100, -48), "#E4EFFF");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-48, -45), "#DCE9FA");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-45, -42), "#D3E2F7");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-42, -40), "#CBDBF4");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-40, -37), "#C0D4ED");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-37, -34), "#B8CDEA");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-34, -31), "#AFC6E6");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-31, -28), "#A7BFE3");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-28, -26), "#9CB8DF");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-26, -23), "#93B1D6");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-23, -20), "#89A4CD");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-20, -17), "#7F9BC3");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-17, -15), "#7590B9");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-15, -12), "#617AA8");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-12, -9), "#56719C");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-9, -6), "#4D6591");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-6, -3), "#415C87");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-3, -1), "#39517F");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(-1, 1), "#2F4577");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(1, 4), "#26436F");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(4, 7), "#254F77");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(7, 10), "#275B80");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(10, 12), "#27678A");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(12, 15), "#287593");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(15, 18), "#438190");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(18, 21), "#648C89");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(21, 23), "#879A84");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(23, 26), "#ABA87D");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(26, 29), "#C2A875");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(29, 32), "#C19D61");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(32, 35), "#C38A53");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(35, 37), "#BE704C");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(37, 40), "#AF4D4C");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(40, 43), "#9F294C");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(43, 46), "#87203E");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(46, 48), "#631531");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(48, 65), "#560C25");
|
||||
TEMPERATURE_COLOR_MAP.put(Pair.of(65, 100), "#3D0216");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getColorForTemperature(Float temperature) {
|
||||
return Color.decode(TEMPERATURE_COLOR_MAP.get(TEMPERATURE_COLOR_MAP
|
||||
.keySet()
|
||||
.stream()
|
||||
.filter(pair -> pair.getLeft() < temperature && pair.getRight() > temperature)
|
||||
.findFirst().orElse(TEMPERATURE_COLOR_MAP.keySet().iterator().next())));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd">
|
||||
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
|
||||
<property name="openWeatherMapFeature" value="(SELECT id FROM feature WHERE key = 'openWeatherMap')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="openWeatherMap-command">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="openWeatherMap"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${openWeatherMapFeature}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="feature.xml" relativeToChangelogFile="true"/>
|
||||
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="openWeatherMap_feature-insertion">
|
||||
<insert tableName="feature">
|
||||
<column name="key" value="openWeatherMap"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -8,4 +8,5 @@
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="1.2.5-webservices/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.4.7/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.4.22/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -15,4 +15,16 @@ abstracto.featureModes.videoDetails.mode=videoDetails
|
||||
abstracto.featureModes.videoDetails.enabled=false
|
||||
|
||||
abstracto.featureFlags.threadReader.featureName=threadReader
|
||||
abstracto.featureFlags.threadReader.enabled=false
|
||||
abstracto.featureFlags.threadReader.enabled=false
|
||||
|
||||
|
||||
abstracto.feature.webservices.openweathermap.geocodingURL=http://api.openweathermap.org/geo/1.0/direct?q=%s&limit=%s&appid=%s
|
||||
abstracto.feature.webservices.openweathermap.weatherDataURL=https://api.openweathermap.org/data/2.5/weather?lat=%s&lon=%s&appid=%s&units=metric&lang=%s
|
||||
|
||||
abstracto.feature.webservices.openweatherMap.apiKey=${OPEN_WEATHER_MAP_API_KEY}
|
||||
|
||||
abstracto.featureFlags.openWeatherMap.featureName=openWeatherMap
|
||||
abstracto.featureFlags.openWeatherMap.enabled=false
|
||||
|
||||
abstracto.systemConfigs.openWeatherMapLanguageKey.name=openWeatherMapLanguageKey
|
||||
abstracto.systemConfigs.openWeatherMapLanguageKey.stringValue=en
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>webservices</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -14,4 +14,11 @@
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -3,4 +3,5 @@ package dev.sheldan.abstracto.webservices.config;
|
||||
public class WebServicesSlashCommandNames {
|
||||
public static final String YOUTUBE = "youtube";
|
||||
public static final String URBAN = "urban";
|
||||
public static final String WEATHER = "weather";
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum WebserviceFeatureDefinition implements FeatureDefinition {
|
||||
YOUTUBE("youtube"), URBAN_DICTIONARY("urban"), THREAD_READER("threadReader");
|
||||
YOUTUBE("youtube"),
|
||||
URBAN_DICTIONARY("urban"),
|
||||
THREAD_READER("threadReader"),
|
||||
OPEN_WEATHER_MAP("openWeatherMap");
|
||||
|
||||
private String key;
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.webservices.config.WebserviceFeatureDefinition;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class OpenWeatherMapConfig implements FeatureConfig {
|
||||
|
||||
public static final String OPEN_WEATHER_MAP_LANGUAGE_KEY_SYSTEM_CONFIG_KEY = "openWeatherMapLanguageKey";
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return WebserviceFeatureDefinition.OPEN_WEATHER_MAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRequiredSystemConfigKeys() {
|
||||
return Arrays.asList(OPEN_WEATHER_MAP_LANGUAGE_KEY_SYSTEM_CONFIG_KEY);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
public class LocationNotFoundException extends AbstractoTemplatableException {
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "no_weather_location_found_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class GeoCodingLocation {
|
||||
@SerializedName("name")
|
||||
private String name;
|
||||
@SerializedName("lat")
|
||||
private Double latitude;
|
||||
@SerializedName("lon")
|
||||
private Double longitude;
|
||||
@SerializedName("country")
|
||||
private String countryKey;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class GeoCodingResult {
|
||||
private List<GeoCodingLocation> results;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.awt.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class WeatherResponseModel {
|
||||
private Float temperature;
|
||||
private Float minTemperature;
|
||||
private Float maxTemperature;
|
||||
private String mainWeather;
|
||||
private String description;
|
||||
private Float feelsLikeTemperature;
|
||||
private Integer humidity;
|
||||
private Integer pressure;
|
||||
private Integer seaLevelPressure;
|
||||
private Integer groundLevelPressure;
|
||||
private Float rain1H;
|
||||
private Float rain3H;
|
||||
private Float snow1H;
|
||||
private Float snow3H;
|
||||
private Integer clouds;
|
||||
private Instant sunrise;
|
||||
private Instant sunset;
|
||||
private Integer visibility;
|
||||
private Instant dataCalculationTime;
|
||||
private String locationName;
|
||||
private String countryKey;
|
||||
private Color embedColor;
|
||||
private Long locationId;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class WeatherResult {
|
||||
@SerializedName("coord")
|
||||
private WeatherResultCoordinates coordinates;
|
||||
@SerializedName("weather")
|
||||
private List<WeatherResultWeatherDescription> weathers;
|
||||
@SerializedName("visibility")
|
||||
private Integer visibility;
|
||||
@SerializedName("main")
|
||||
private WeatherResultMain mainWeather;
|
||||
@SerializedName("rain")
|
||||
private WeatherResultRain rainInfo;
|
||||
@SerializedName("snow")
|
||||
private WeatherResultSnow snowInfo;
|
||||
@SerializedName("dt")
|
||||
private Long dayTime;
|
||||
@SerializedName("clouds")
|
||||
private WeatherResultClouds cloudInfo;
|
||||
@SerializedName("sys")
|
||||
private WeatherResultSystem systemInfo;
|
||||
@SerializedName("timezone")
|
||||
private Long timezoneShift;
|
||||
@SerializedName("id")
|
||||
private Long locationId;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class WeatherResultClouds {
|
||||
private Integer all;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class WeatherResultCoordinates {
|
||||
@SerializedName("lon")
|
||||
private Float longitude;
|
||||
@SerializedName("lat")
|
||||
private Float latitude;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class WeatherResultMain {
|
||||
@SerializedName("temp")
|
||||
private Float temperature;
|
||||
@SerializedName("feels_like")
|
||||
private Float feelsLikeTemperature;
|
||||
@SerializedName("temp_min")
|
||||
private Float minTemperature;
|
||||
@SerializedName("temp_max")
|
||||
private Float maxTemperature;
|
||||
@SerializedName("pressure")
|
||||
private Integer pressure;
|
||||
@SerializedName("humidity")
|
||||
private Integer humidity;
|
||||
@SerializedName("sea_level")
|
||||
private Integer seaLevelPressure;
|
||||
@SerializedName("grnd_level")
|
||||
private Integer groundLevelPressure;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class WeatherResultRain {
|
||||
@SerializedName("1h")
|
||||
private Float rain1H;
|
||||
|
||||
@SerializedName("3h")
|
||||
private Float rain3H;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class WeatherResultSnow {
|
||||
@SerializedName("1h")
|
||||
private Float snow1H;
|
||||
|
||||
@SerializedName("3h")
|
||||
private Float snow3H;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class WeatherResultSystem {
|
||||
@SerializedName("country")
|
||||
private String country;
|
||||
|
||||
@SerializedName("sunrise")
|
||||
private Long sunrise;
|
||||
|
||||
@SerializedName("sunset")
|
||||
private Long sunset;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class WeatherResultWeatherDescription {
|
||||
private Long id;
|
||||
private String main;
|
||||
private String description;
|
||||
private String icon;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class WeatherResultWind {
|
||||
@SerializedName("speed")
|
||||
private Float speed;
|
||||
@SerializedName("deg")
|
||||
private Integer degrees;
|
||||
@SerializedName("gust")
|
||||
private Float gust;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.service;
|
||||
|
||||
import dev.sheldan.abstracto.webservices.openweathermap.model.GeoCodingLocation;
|
||||
import dev.sheldan.abstracto.webservices.openweathermap.model.GeoCodingResult;
|
||||
import dev.sheldan.abstracto.webservices.openweathermap.model.WeatherResult;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface OpenWeatherMapService {
|
||||
GeoCodingResult searchForLocation(String query) throws IOException;
|
||||
WeatherResult retrieveWeatherForLocation(GeoCodingLocation geoCodingLocation, String languageKey) throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.sheldan.abstracto.webservices.openweathermap.service;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public interface WeatherService {
|
||||
Color getColorForTemperature(Float temperature);
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto</groupId>
|
||||
<artifactId>abstracto-application</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>1.4.21</version>
|
||||
<version>1.4.25</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@@ -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.commands.config.ConfigModuleDefinition;
|
||||
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.UploadFileTooLargeException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.GetCustomTemplateModel;
|
||||
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.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -67,28 +63,10 @@ public class GetCustomTemplate extends AbstractConditionableCommand {
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
String templateKey = (String) commandContext.getParameters().getParameters().get(0);
|
||||
GetCustomTemplateModel model = getModel(templateKey, commandContext.getGuild());
|
||||
File tempFile = fileService.createTempFile(templateKey + ".ftl");
|
||||
try {
|
||||
fileService.writeContentToFile(tempFile, model.getTemplateContent());
|
||||
long maxFileSize = commandContext.getGuild().getIdLong();
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(GET_CUSTOM_TEMPLATE_RESPONSE_TEMPLATE_KEY, model, commandContext.getGuild().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenAccept(interactionHook -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
private GetCustomTemplateModel getModel(String templateKey, Guild guild) {
|
||||
@@ -109,27 +87,10 @@ public class GetCustomTemplate extends AbstractConditionableCommand {
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String templateKey = slashCommandParameterService.getCommandOption(TEMPLATE_KEY_PARAMETER, event, String.class);
|
||||
GetCustomTemplateModel model = getModel(templateKey, event.getGuild());
|
||||
File tempFile = fileService.createTempFile(templateKey + ".ftl");
|
||||
try {
|
||||
fileService.writeContentToFile(tempFile, model.getTemplateContent());
|
||||
long maxFileSize = event.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(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);
|
||||
}
|
||||
}
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(GET_CUSTOM_TEMPLATE_RESPONSE_TEMPLATE_KEY, model, event.getGuild().getIdLong());
|
||||
return interactionService.replyMessageToSend(messageToSend, event)
|
||||
.thenAccept(interactionHook -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@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.commands.config.ConfigModuleDefinition;
|
||||
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.interaction.InteractionService;
|
||||
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.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -63,44 +60,20 @@ public class GetTemplate extends AbstractConditionableCommand {
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
String templateKey = (String) commandContext.getParameters().getParameters().get(0);
|
||||
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.getAttachedFiles().get(0).setFile(tempFile);
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenAccept(interactionHook -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
|
||||
.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
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String templateKey = slashCommandParameterService.getCommandOption(TEMPLATE_KEY_PARAMETER, event, String.class);
|
||||
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.getAttachedFiles().get(0).setFile(tempFile);
|
||||
return interactionService.replyMessageToSend(messageToSend, event)
|
||||
.thenAccept(interactionHook -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
|
||||
.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) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user