From edcc0c7eb465b15d00bc54cb6a2b401b8c8518ed Mon Sep 17 00:00:00 2001 From: Daniel Villavicencio Date: Tue, 12 Mar 2024 18:40:49 -0700 Subject: [PATCH] Fixed tests and removed controller advice --- build.gradle | 1 + .../destiny2bot/Destiny2botApplication.java | 28 +-- .../destiny2bot/client/BungieClient.java | 22 ++- .../client/BungieClientWrapper.java | 35 ---- .../config/BungieConfiguration.java | 7 +- .../controller/GlobalExceptionHandler.java | 35 ---- .../dto/destiny/ExactUserSearchRequest.java | 13 ++ .../dto/destiny/ExactUserSearchResponse.java | 21 +++ ...ields.java => ManifestResponseFields.java} | 2 +- .../destiny2bot/dto/discord/Option.java | 6 + .../filter/SignatureFilterFunction.java | 1 + .../handler/InteractionHandler.java | 12 +- .../destiny2bot/handler/RaidStatsHandler.java | 63 +++++-- .../destiny2bot/service/BungieAPIService.java | 99 ++++++++++ .../service/PostGameCarnageService.java | 2 +- .../destiny2bot/service/RaidStatsService.java | 1 + .../service/UserRaidDetailsService.java | 89 ++++----- .../service/WeeklyActivitiesService.java | 45 ++--- src/main/resources/application-local.yml | 6 +- .../handler/RaidMapHandlerTest.java | 32 ++-- .../InteractionControllerTest.java | 12 +- .../service/RaidInfographicsServiceTest.java | 9 +- .../service/UserRaidDetailsServiceTest.java | 173 ++++++++---------- .../service/WeeklyActivitiesServiceTest.java | 104 +++++------ .../__files/bungie/milestone-response.json | 2 +- 25 files changed, 434 insertions(+), 386 deletions(-) delete mode 100644 src/main/java/com/danielvm/destiny2bot/client/BungieClientWrapper.java delete mode 100644 src/main/java/com/danielvm/destiny2bot/controller/GlobalExceptionHandler.java create mode 100644 src/main/java/com/danielvm/destiny2bot/dto/destiny/ExactUserSearchRequest.java create mode 100644 src/main/java/com/danielvm/destiny2bot/dto/destiny/ExactUserSearchResponse.java rename src/main/java/com/danielvm/destiny2bot/dto/destiny/manifest/{ResponseFields.java => ManifestResponseFields.java} (93%) create mode 100644 src/main/java/com/danielvm/destiny2bot/service/BungieAPIService.java diff --git a/build.gradle b/build.gradle index a123d97..6d0d5cb 100644 --- a/build.gradle +++ b/build.gradle @@ -69,6 +69,7 @@ dependencies { implementation "commons-codec:commons-codec:${commonsCodecVersion}" implementation "software.pando.crypto:salty-coffee:${pandoCryptoVersion}" implementation "org.apache.commons:commons-collections4:${apacheCollectionsVersion}" + implementation 'org.springframework.boot:spring-boot-starter-actuator' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' annotationProcessor "org.mapstruct:mapstruct-processor:${mapStructVersion}" diff --git a/src/main/java/com/danielvm/destiny2bot/Destiny2botApplication.java b/src/main/java/com/danielvm/destiny2bot/Destiny2botApplication.java index a6b3871..2387ec0 100644 --- a/src/main/java/com/danielvm/destiny2bot/Destiny2botApplication.java +++ b/src/main/java/com/danielvm/destiny2bot/Destiny2botApplication.java @@ -1,13 +1,10 @@ package com.danielvm.destiny2bot; -import com.danielvm.destiny2bot.exception.ExternalServiceException; -import com.danielvm.destiny2bot.exception.InternalServerException; import com.danielvm.destiny2bot.filter.SignatureFilterFunction; import com.danielvm.destiny2bot.handler.InteractionHandler; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import java.nio.charset.StandardCharsets; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -17,13 +14,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.http.HttpStatus; -import org.springframework.http.HttpStatusCode; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; -import reactor.core.publisher.Mono; @Slf4j @EnableCaching @@ -36,7 +30,7 @@ public static void main(String[] args) { } @Bean - RouterFunction interactionFilterFunction( + RouterFunction interactionRouterFunction( InteractionHandler interactionHandler, SignatureFilterFunction signatureFilterFunction) { return RouterFunctions.route() @@ -72,25 +66,7 @@ CacheManager inMemoryCacheManager() { */ @Bean public WebClient.Builder webClient() { - return WebClient.builder() - .defaultStatusHandler( - HttpStatusCode::is5xxServerError, - clientResponse -> clientResponse.createException() - .flatMap(ce -> Mono.error(new ExternalServiceException( - ce.getResponseBodyAsString(StandardCharsets.UTF_8), - HttpStatus.INTERNAL_SERVER_ERROR, - ce.getCause())) - ) - ) - .defaultStatusHandler( - HttpStatusCode::is4xxClientError, - clientResponse -> clientResponse.createException() - .flatMap(ce -> Mono.error( - new InternalServerException( - ce.getResponseBodyAsString(StandardCharsets.UTF_8), - HttpStatus.BAD_REQUEST) - )) - ); + return WebClient.builder(); } @Bean diff --git a/src/main/java/com/danielvm/destiny2bot/client/BungieClient.java b/src/main/java/com/danielvm/destiny2bot/client/BungieClient.java index 1193cb4..ab75149 100644 --- a/src/main/java/com/danielvm/destiny2bot/client/BungieClient.java +++ b/src/main/java/com/danielvm/destiny2bot/client/BungieClient.java @@ -2,15 +2,18 @@ import com.danielvm.destiny2bot.dto.destiny.ActivitiesResponse; import com.danielvm.destiny2bot.dto.destiny.BungieResponse; +import com.danielvm.destiny2bot.dto.destiny.ExactUserSearchRequest; +import com.danielvm.destiny2bot.dto.destiny.ExactUserSearchResponse; import com.danielvm.destiny2bot.dto.destiny.MemberGroupResponse; import com.danielvm.destiny2bot.dto.destiny.MembershipResponse; import com.danielvm.destiny2bot.dto.destiny.PostGameCarnageReport; import com.danielvm.destiny2bot.dto.destiny.SearchResult; import com.danielvm.destiny2bot.dto.destiny.UserGlobalSearchBody; import com.danielvm.destiny2bot.dto.destiny.characters.CharactersResponse; -import com.danielvm.destiny2bot.dto.destiny.manifest.ResponseFields; +import com.danielvm.destiny2bot.dto.destiny.manifest.ManifestResponseFields; import com.danielvm.destiny2bot.dto.destiny.milestone.MilestoneEntry; import com.danielvm.destiny2bot.enums.ManifestEntity; +import java.util.List; import java.util.Map; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -40,10 +43,10 @@ Mono> getMembershipInfoById( * * @param entityType The entity type (see {@link ManifestEntity}) * @param hashIdentifier The entity hash identifier - * @return {@link Mono} of {@link ResponseFields} + * @return {@link Mono} of {@link ManifestResponseFields} */ @GetExchange("/Destiny2/Manifest/{entityType}/{hashIdentifier}/") - Mono> getManifestEntity( + Mono> getManifestEntity( @PathVariable String entityType, @PathVariable Long hashIdentifier); /** @@ -52,7 +55,7 @@ Mono> getManifestEntity( * @return {@link Mono} of Map of {@link MilestoneEntry} */ @GetExchange("/Destiny2/Milestones/") - Mono>> getPublicMilestonesRx(); + Mono>> getPublicMilestones(); /** * Get a user characters @@ -121,4 +124,15 @@ Mono> getActivityHistory(@PathVariable Intege Mono> getPostGameCarnageReport( @PathVariable Long activityId ); + + /** + * Search for a Destiny 2 membership using exact parameters, that is, name and code + * + * @param request The request to make to Bungie for an exact user search + * @return {@link ExactUserSearchRequest} + */ + @PostExchange("/Destiny2/SearchDestinyPlayerByBungieName/-1/") + Mono>> searchUserByExactNameAndCode( + @RequestBody ExactUserSearchRequest request + ); } diff --git a/src/main/java/com/danielvm/destiny2bot/client/BungieClientWrapper.java b/src/main/java/com/danielvm/destiny2bot/client/BungieClientWrapper.java deleted file mode 100644 index 78c582b..0000000 --- a/src/main/java/com/danielvm/destiny2bot/client/BungieClientWrapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.danielvm.destiny2bot.client; - -import com.danielvm.destiny2bot.dto.destiny.BungieResponse; -import com.danielvm.destiny2bot.dto.destiny.manifest.ResponseFields; -import com.danielvm.destiny2bot.enums.ManifestEntity; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Component; -import reactor.core.publisher.Mono; - -/** - * This Bungie Client wrapper class is responsible for caching manifest entities - */ -@Component -public class BungieClientWrapper { - - private final BungieClient defaultBungieClient; - - public BungieClientWrapper(BungieClient defaultBungieClient) { - this.defaultBungieClient = defaultBungieClient; - } - - /** - * Wraps the client call to the Manifest with a Cacheable method - * - * @param entityType The entity type (see {@link ManifestEntity}) - * @param hashIdentifier The hash identifier - * @return {@link BungieResponse} of {@link ResponseFields} - */ - @Cacheable(cacheNames = "entity", cacheManager = "inMemoryCacheManager") - public Mono> getManifestEntity( - ManifestEntity entityType, Long hashIdentifier) { - return defaultBungieClient.getManifestEntity(entityType.getId(), hashIdentifier).cache(); - } - -} diff --git a/src/main/java/com/danielvm/destiny2bot/config/BungieConfiguration.java b/src/main/java/com/danielvm/destiny2bot/config/BungieConfiguration.java index 6b78b16..f241509 100644 --- a/src/main/java/com/danielvm/destiny2bot/config/BungieConfiguration.java +++ b/src/main/java/com/danielvm/destiny2bot/config/BungieConfiguration.java @@ -78,7 +78,7 @@ public BungieClient bungieCharacterClient(WebClient.Builder builder) { .clientConnector(new ReactorClientHttpConnector(httpClient)) .defaultHeader(API_KEY_HEADER_NAME, this.key) .codecs(clientCodecConfigurer -> clientCodecConfigurer.defaultCodecs() - .maxInMemorySize(1024 * 1024)) + .maxInMemorySize(1024 * 512)) .build(); return HttpServiceProxyFactory.builder() .exchangeAdapter(WebClientAdapter.create(webClient)) @@ -95,16 +95,13 @@ public BungieClient bungieCharacterClient(WebClient.Builder builder) { @Bean(name = "pgcrBungieClient") public BungieClient pgcrBungieClient(WebClient.Builder builder) { // Don't keep alive connections with Bungie.net - HttpClient httpClient = HttpClient.create() - .keepAlive(false); var webClient = builder .baseUrl(this.statsBaseUrl) - .clientConnector(new ReactorClientHttpConnector(httpClient)) .defaultHeader(API_KEY_HEADER_NAME, this.key) .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .codecs(clientCodecConfigurer -> clientCodecConfigurer.defaultCodecs() - .maxInMemorySize(1024 * 1024 * 5)) + .maxInMemorySize(1024 * 20)) .build(); return HttpServiceProxyFactory.builder() .exchangeAdapter(WebClientAdapter.create(webClient)) diff --git a/src/main/java/com/danielvm/destiny2bot/controller/GlobalExceptionHandler.java b/src/main/java/com/danielvm/destiny2bot/controller/GlobalExceptionHandler.java deleted file mode 100644 index 0528e8e..0000000 --- a/src/main/java/com/danielvm/destiny2bot/controller/GlobalExceptionHandler.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.danielvm.destiny2bot.controller; - -import com.danielvm.destiny2bot.exception.BaseException; -import jakarta.validation.ConstraintViolationException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ProblemDetail; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import org.springframework.web.reactive.function.client.WebClientResponseException; - -@RestControllerAdvice -public class GlobalExceptionHandler { - - @ExceptionHandler - public ProblemDetail handleWebClientException(WebClientResponseException wcre) { - var detail = ProblemDetail.forStatus(HttpStatus.BAD_REQUEST); - detail.setDetail(wcre.getResponseBodyAsString()); - return detail; - } - - @ExceptionHandler - public ProblemDetail handleConstraintViolationException(ConstraintViolationException cve) { - var detail = ProblemDetail.forStatus(HttpStatus.BAD_REQUEST); - detail.setDetail(cve.getMessage()); - return detail; - } - - @ExceptionHandler - public ProblemDetail handleBaseException(BaseException baseException) { - var detail = ProblemDetail.forStatus(baseException.getStatus()); - detail.setDetail(baseException.getMessage()); - return detail; - } - -} diff --git a/src/main/java/com/danielvm/destiny2bot/dto/destiny/ExactUserSearchRequest.java b/src/main/java/com/danielvm/destiny2bot/dto/destiny/ExactUserSearchRequest.java new file mode 100644 index 0000000..0072be6 --- /dev/null +++ b/src/main/java/com/danielvm/destiny2bot/dto/destiny/ExactUserSearchRequest.java @@ -0,0 +1,13 @@ +package com.danielvm.destiny2bot.dto.destiny; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class ExactUserSearchRequest { + + private String displayName; + + private Integer displayNameCode; +} diff --git a/src/main/java/com/danielvm/destiny2bot/dto/destiny/ExactUserSearchResponse.java b/src/main/java/com/danielvm/destiny2bot/dto/destiny/ExactUserSearchResponse.java new file mode 100644 index 0000000..4127769 --- /dev/null +++ b/src/main/java/com/danielvm/destiny2bot/dto/destiny/ExactUserSearchResponse.java @@ -0,0 +1,21 @@ +package com.danielvm.destiny2bot.dto.destiny; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ExactUserSearchResponse { + + private String bungieGlobalDisplayName; + + private Integer bungieGlobalDisplayNameCode; + + private Integer membershipType; + + private String membershipId; + + private String displayName; +} diff --git a/src/main/java/com/danielvm/destiny2bot/dto/destiny/manifest/ResponseFields.java b/src/main/java/com/danielvm/destiny2bot/dto/destiny/manifest/ManifestResponseFields.java similarity index 93% rename from src/main/java/com/danielvm/destiny2bot/dto/destiny/manifest/ResponseFields.java rename to src/main/java/com/danielvm/destiny2bot/dto/destiny/manifest/ManifestResponseFields.java index 32e28fb..080c3d9 100644 --- a/src/main/java/com/danielvm/destiny2bot/dto/destiny/manifest/ResponseFields.java +++ b/src/main/java/com/danielvm/destiny2bot/dto/destiny/manifest/ManifestResponseFields.java @@ -9,7 +9,7 @@ @AllArgsConstructor @NoArgsConstructor @Builder -public class ResponseFields { +public class ManifestResponseFields { private DisplayProperties displayProperties; diff --git a/src/main/java/com/danielvm/destiny2bot/dto/discord/Option.java b/src/main/java/com/danielvm/destiny2bot/dto/discord/Option.java index 41605b7..ca78857 100644 --- a/src/main/java/com/danielvm/destiny2bot/dto/discord/Option.java +++ b/src/main/java/com/danielvm/destiny2bot/dto/discord/Option.java @@ -1,5 +1,6 @@ package com.danielvm.destiny2bot.dto.discord; +import java.util.List; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -29,4 +30,9 @@ public class Option { */ private Boolean focused; + /** + * The list of options that belong to this sub-command or sub-command group + */ + private List