From b1103119b6d0e796e94bb8a433ba9aaf739a556c Mon Sep 17 00:00:00 2001 From: grimsi Date: Mon, 4 Jul 2022 20:57:24 +0200 Subject: [PATCH] Initial commit 3: Will it work this time? --- .gitignore | 1 + pom.xml | 26 +++++--- .../java/de/grimsi/gameyfin/dto/GameDto.java | 4 ++ .../de/grimsi/gameyfin/igdb/IgdbWrapper.java | 61 ++++++++++--------- .../gameyfin/igdb/dto/IgdbAccessToken.java | 2 +- .../de/grimsi/gameyfin/igdb/dto/IgdbGame.java | 45 +++++++++++++- .../gameyfin/rest/GameyfinDevController.java | 5 +- .../gameyfin/service/FilesystemService.java | 10 ++- src/main/resources/application-dev.yml | 2 +- 9 files changed, 110 insertions(+), 46 deletions(-) diff --git a/.gitignore b/.gitignore index 549e00a..32de00b 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ build/ ### VS Code ### .vscode/ +/.mvn/ diff --git a/pom.xml b/pom.xml index 8b3fbb4..82f52c4 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,7 @@ + org.springframework.boot spring-boot-starter-data-jpa @@ -34,17 +35,27 @@ spring-boot-starter-webflux + + + com.h2database + h2 + runtime + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot spring-boot-devtools runtime true - - com.h2database - h2 - runtime - org.springframework.boot spring-boot-configuration-processor @@ -55,11 +66,6 @@ lombok true - - org.springframework.boot - spring-boot-starter-test - test - diff --git a/src/main/java/de/grimsi/gameyfin/dto/GameDto.java b/src/main/java/de/grimsi/gameyfin/dto/GameDto.java index 7aa6caa..8c83568 100644 --- a/src/main/java/de/grimsi/gameyfin/dto/GameDto.java +++ b/src/main/java/de/grimsi/gameyfin/dto/GameDto.java @@ -1,7 +1,9 @@ package de.grimsi.gameyfin.dto; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import java.io.File; import java.time.Instant; @@ -9,6 +11,8 @@ import java.util.List; @Data @Builder +@NoArgsConstructor +@AllArgsConstructor public class GameDto { private String name; private String publisher; diff --git a/src/main/java/de/grimsi/gameyfin/igdb/IgdbWrapper.java b/src/main/java/de/grimsi/gameyfin/igdb/IgdbWrapper.java index 05dd32e..300ae8a 100644 --- a/src/main/java/de/grimsi/gameyfin/igdb/IgdbWrapper.java +++ b/src/main/java/de/grimsi/gameyfin/igdb/IgdbWrapper.java @@ -1,6 +1,7 @@ package de.grimsi.gameyfin.igdb; -import de.grimsi.gameyfin.dto.GameDto; +import de.grimsi.gameyfin.igdb.dto.IgdbAccessToken; +import de.grimsi.gameyfin.igdb.dto.IgdbGame; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; @@ -10,7 +11,6 @@ import org.springframework.web.util.UriComponentsBuilder; import javax.annotation.PostConstruct; import java.net.URI; -import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -37,6 +37,7 @@ public class IgdbWrapper { @PostConstruct public void init() { authenticate(); + initIgdbClient(); } public void authenticate() { @@ -58,8 +59,23 @@ public class IgdbWrapper { log.info("Successfully authenticated."); } + public IgdbGame findGameByTitle(String title) { + return searchForGameByTitle(title).orElseThrow(() -> new RuntimeException("Could not find game with title: \"%s\"".formatted(title))); + } + + private Optional getGameById(Long id) { + return Optional.ofNullable( + igdbApiClient.post() + .uri("games") + .bodyValue("fields *; where id = %d;".formatted(id)) + .retrieve() + .bodyToMono(IgdbGame.class) + .block() + ); + } + private void initIgdbClient() { - if(accessToken == null) { + if (accessToken == null) { authenticate(); } @@ -70,46 +86,33 @@ public class IgdbWrapper { .build(); } - public GameDto findGameByTitle(String title) { - if (igdbApiClient == null) { - initIgdbClient(); - } - - IgdbSearchResultDto searchResult = searchForGameByTitle(title).orElseThrow(() -> new RuntimeException("Could not find game with title : \"%s\"".formatted(title))); - - return GameDto.builder() - .name(searchResult.getName()) - .releaseDate(Instant.ofEpochSecond(searchResult.getPublishedAt())) - .igdbGameId(searchResult.getGame()) - .build(); - } - - public Optional searchForGameByTitle(String searchTerm) { - List searchResults = new ArrayList<>(); + private Optional searchForGameByTitle(String searchTerm) { + List games = new ArrayList<>(); igdbApiClient.post() - .uri("search") - .bodyValue("fields *; search \"%s\"; limit 50;".formatted(searchTerm)) + .uri("games") + .bodyValue("fields *; search \"%s\";".formatted(searchTerm)) .retrieve() - .bodyToFlux(IgdbSearchResultDto.class) - .doOnNext(searchResults::add) + .bodyToFlux(IgdbGame.class) + .doOnNext(games::add) .blockLast(); - if(searchResults.isEmpty()) return Optional.empty(); + if (games.isEmpty()) return Optional.empty(); // First check if there are any matches with the exact search term // If no exact match has been found, check if there are matches where the name ends with the search term // This will filter out most DLCs and similiar stuff, but will detect a game even when your search term is not exactly the title + // If that also returns nothing, just return the first search result // // Example: Searching for "Rainbow Six Siege" will result in returning "Tom Clancy's Rainbow Six Siege" (the game we want) // If we just used the first result from IGDB we would get something like "Tom Clancy's Rainbow Six Siege Demon Veil" as a result - Optional srExactTitleMatch = searchResults.stream().filter(s -> s.getName().equals(searchTerm)).findFirst(); - if(srExactTitleMatch.isPresent()) return srExactTitleMatch; + Optional srExactTitleMatch = games.stream().filter(s -> s.getName().equals(searchTerm)).findFirst(); + if (srExactTitleMatch.isPresent()) return srExactTitleMatch; - Optional srTitleEndsWithMatch = searchResults.stream().filter(s -> s.getName().endsWith(searchTerm)).findFirst(); - if(srTitleEndsWithMatch.isPresent()) return srTitleEndsWithMatch; + Optional srTitleEndsWithMatch = games.stream().filter(s -> s.getName().endsWith(searchTerm)).findFirst(); + if (srTitleEndsWithMatch.isPresent()) return srTitleEndsWithMatch; - return Optional.of(searchResults.get(0)); + return Optional.of(games.get(0)); } } diff --git a/src/main/java/de/grimsi/gameyfin/igdb/dto/IgdbAccessToken.java b/src/main/java/de/grimsi/gameyfin/igdb/dto/IgdbAccessToken.java index 5d886b1..70fce65 100644 --- a/src/main/java/de/grimsi/gameyfin/igdb/dto/IgdbAccessToken.java +++ b/src/main/java/de/grimsi/gameyfin/igdb/dto/IgdbAccessToken.java @@ -1,4 +1,4 @@ -package de.grimsi.gameyfin.igdb; +package de.grimsi.gameyfin.igdb.dto; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; diff --git a/src/main/java/de/grimsi/gameyfin/igdb/dto/IgdbGame.java b/src/main/java/de/grimsi/gameyfin/igdb/dto/IgdbGame.java index 39500ed..80d8646 100644 --- a/src/main/java/de/grimsi/gameyfin/igdb/dto/IgdbGame.java +++ b/src/main/java/de/grimsi/gameyfin/igdb/dto/IgdbGame.java @@ -1,2 +1,45 @@ -package de.grimsi.gameyfin.igdb.dto;public class IgdbGame { +package de.grimsi.gameyfin.igdb.dto; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.Instant; +import java.util.List; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class IgdbGame { + private Long id; + private List alternativeNames; + private Long category; + private Long cover; + private Instant createdAt; + private List externalGames; + private Instant firstReleaseDate; + private Long follows; + private List gameModes; + private List genres; + private Long hypes; + private List involvedCompanies; + private List keywords; + private List multiplayerModes; + private String name; + private List platforms; + private List playerPerspectives; + private Float rating; + private Long ratingCount; + private List releaseDates; + private List screenshots; + private List similiarGames; + private String slug; + private String storyline; + private String summary; + private List tags; } diff --git a/src/main/java/de/grimsi/gameyfin/rest/GameyfinDevController.java b/src/main/java/de/grimsi/gameyfin/rest/GameyfinDevController.java index f86e13e..004cece 100644 --- a/src/main/java/de/grimsi/gameyfin/rest/GameyfinDevController.java +++ b/src/main/java/de/grimsi/gameyfin/rest/GameyfinDevController.java @@ -9,16 +9,15 @@ import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.client.HttpStatusCodeException; import org.springframework.web.server.ResponseStatusException; @RestController -public class GameyfinController { +public class GameyfinDevController { @Autowired IgdbWrapper igdbWrapper; - @GetMapping(value = "/findGameByTitle/{title}", produces = MediaType.APPLICATION_JSON_VALUE) + @GetMapping(value = "/dev/findGameByTitle/{title}", produces = MediaType.APPLICATION_JSON_VALUE) public GameDto findGameByTitle(@PathVariable("title") String title) { IgdbGame game; diff --git a/src/main/java/de/grimsi/gameyfin/service/FilesystemService.java b/src/main/java/de/grimsi/gameyfin/service/FilesystemService.java index 99d71cd..870efb1 100644 --- a/src/main/java/de/grimsi/gameyfin/service/FilesystemService.java +++ b/src/main/java/de/grimsi/gameyfin/service/FilesystemService.java @@ -1,2 +1,10 @@ -package de.grimsi.gameyfin.service;public class FilesystemService { +package de.grimsi.gameyfin.service; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class FilesystemService { + @Value("${gameyfin.root}") + private String rootFolderPath; } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index bf79d63..6ea1869 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -1,5 +1,5 @@ gameyfin: - root: F:\Spiele + root: D:\Games igdb: api: client-id: 23l3l5qshx4dwjuao6yb8jyf1qrd08