mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-14 08:15:27 +00:00
Fixed complex property handling
This commit is contained in:
@@ -2,8 +2,10 @@ package de.grimsi.gameyfin;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
|
||||
|
||||
@SpringBootApplication
|
||||
@ConfigurationPropertiesScan
|
||||
public class GameyfinApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -24,7 +24,9 @@ import java.util.stream.StreamSupport;
|
||||
@RequiredArgsConstructor
|
||||
public class GameyfinFolderConfig {
|
||||
|
||||
private static final String INTERNAL_FOLDER_NAME = ".gameyfin";
|
||||
|
||||
@Value("${gameyfin.internal-folder}")
|
||||
private String INTERNAL_FOLDER_NAME;
|
||||
|
||||
/**
|
||||
* The following SpEL expression will:
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package de.grimsi.gameyfin.config.properties;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// see https://stackoverflow.com/questions/26699385/spring-boot-yaml-configuration-for-a-list-of-strings
|
||||
@ConfigurationProperties("gameyfin")
|
||||
public record GameyfinProperties(
|
||||
folders folders,
|
||||
List<String> fileExtensions,
|
||||
List<String> fileSuffixes,
|
||||
igdb igdb) {
|
||||
|
||||
public record folders(String data) {}
|
||||
|
||||
|
||||
public record igdb(config config) {
|
||||
public record config(List<Integer> preferredPlatforms) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package de.grimsi.gameyfin.igdb;
|
||||
|
||||
import com.igdb.proto.Igdb;
|
||||
import de.grimsi.gameyfin.config.WebClientConfig;
|
||||
import de.grimsi.gameyfin.config.properties.GameyfinProperties;
|
||||
import de.grimsi.gameyfin.dto.AutocompleteSuggestionDto;
|
||||
import de.grimsi.gameyfin.entities.Platform;
|
||||
import de.grimsi.gameyfin.igdb.IgdbApiQueryBuilder.*;
|
||||
@@ -38,12 +39,12 @@ public class IgdbWrapper {
|
||||
private final WebClient.Builder webclientBuilder;
|
||||
private final WebClientConfig webClientConfig;
|
||||
private final GameMapper gameMapper;
|
||||
private final GameyfinProperties gameyfinProperties;
|
||||
|
||||
@Value("${gameyfin.igdb.api.client-id}")
|
||||
private String clientId;
|
||||
@Value("${gameyfin.igdb.api.client-secret}")
|
||||
private String clientSecret;
|
||||
@Value("${gameyfin.igdb.config.preferred-platforms:6}")
|
||||
private List<Integer> preferredPlatforms;
|
||||
@Value("${gameyfin.igdb.api.endpoints.base}")
|
||||
private String igdbApiBaseUrl;
|
||||
@Value("${gameyfin.igdb.api.endpoints.auth}")
|
||||
@@ -119,7 +120,7 @@ public class IgdbWrapper {
|
||||
IgdbApiProperties.ENDPOINT_GAMES_PROTOBUF,
|
||||
queryBuilder.search(searchTerm)
|
||||
.fields("slug,name,first_release_date,platforms.name")
|
||||
.where(in("platforms", preferredPlatforms))
|
||||
.where(in("platforms", gameyfinProperties.igdb().config().preferredPlatforms()))
|
||||
.limit(limit)
|
||||
.build(),
|
||||
Igdb.GameResult.class
|
||||
@@ -137,8 +138,8 @@ public class IgdbWrapper {
|
||||
public Optional<Igdb.Game> searchForGameByTitle(String searchTerm, Collection<String> platformSlugs) {
|
||||
IgdbApiQueryBuilder queryBuilder = new IgdbApiQueryBuilder();
|
||||
Condition platforms = isNotEmpty(platformSlugs) ?
|
||||
and(in("platforms", preferredPlatforms), in("platforms.slug", platformSlugs)) :
|
||||
in("platforms", preferredPlatforms);
|
||||
and(in("platforms", gameyfinProperties.igdb().config().preferredPlatforms()), in("platforms.slug", platformSlugs)) :
|
||||
in("platforms", gameyfinProperties.igdb().config().preferredPlatforms());
|
||||
|
||||
Igdb.GameResult gameResult = queryIgdbApi(
|
||||
IgdbApiProperties.ENDPOINT_GAMES_PROTOBUF,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.grimsi.gameyfin.util;
|
||||
|
||||
import de.grimsi.gameyfin.config.properties.GameyfinProperties;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -20,11 +21,14 @@ public class FilenameUtil {
|
||||
private static final Pattern trailingNoisePattern = Pattern.compile("( |\\(\\)|\\[\\]|[-_.])+$");
|
||||
private static final Pattern headingNoisePattern = Pattern.compile("^( |\\(\\)|\\[\\]|[-_.])+");
|
||||
|
||||
@Value("${gameyfin.file-extensions}")
|
||||
public void setPossibleGameFileExtensions(List<String> possibleGameFileExtensions) {
|
||||
FilenameUtil.possibleGameFileExtensions = possibleGameFileExtensions;
|
||||
public FilenameUtil(GameyfinProperties gameyfinProperties) {
|
||||
possibleGameFileExtensions = gameyfinProperties.fileExtensions();
|
||||
|
||||
// Sort in descending length, so for example "windows" gets checked before "win"
|
||||
FilenameUtil.possibleGameFileSuffixes = gameyfinProperties.fileSuffixes();
|
||||
possibleGameFileSuffixes.sort((s1,s2) -> Integer.compare(s2.length(), s1.length()));
|
||||
}
|
||||
|
||||
|
||||
@Value("${gameyfin.file-suffixes}")
|
||||
public void setPossibleGameFileSuffixes(List<String> possibleGameFileSuffixes) {
|
||||
// Sort in descending length, so for example "windows" gets checked before "win"
|
||||
|
||||
@@ -6,5 +6,6 @@ logging:
|
||||
level:
|
||||
de.grimsi: debug
|
||||
# org.springframework.web.reactive.function.client.ExchangeFunctions: debug
|
||||
org.apache.catalina.core.ContainerBase: info
|
||||
|
||||
spring.mvc.log-request-details: true
|
||||
@@ -5,6 +5,7 @@ import com.google.protobuf.Message;
|
||||
import com.google.protobuf.Timestamp;
|
||||
import com.igdb.proto.Igdb;
|
||||
import de.grimsi.gameyfin.config.WebClientConfig;
|
||||
import de.grimsi.gameyfin.config.properties.GameyfinProperties;
|
||||
import de.grimsi.gameyfin.dto.AutocompleteSuggestionDto;
|
||||
import de.grimsi.gameyfin.entities.Platform;
|
||||
import de.grimsi.gameyfin.igdb.dto.TwitchOAuthTokenDto;
|
||||
@@ -22,6 +23,7 @@ import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
@@ -52,8 +54,9 @@ class IgdbWrapperTest {
|
||||
static void setup() throws IOException, InterruptedException {
|
||||
WebClientConfig webClientConfigMock = mock(WebClientConfig.class);
|
||||
GameMapper gameMapperMock = mock(GameMapper.class);
|
||||
GameyfinProperties gameyfinPropertiesMock = mock(GameyfinProperties.class, Mockito.RETURNS_DEEP_STUBS);
|
||||
|
||||
target = new IgdbWrapper(WebClient.builder(), webClientConfigMock, gameMapperMock);
|
||||
target = new IgdbWrapper(WebClient.builder(), webClientConfigMock, gameMapperMock, gameyfinPropertiesMock);
|
||||
|
||||
igdbApiMock.start();
|
||||
twitchApiMock.start();
|
||||
@@ -62,7 +65,8 @@ class IgdbWrapperTest {
|
||||
ReflectionTestUtils.setField(target, "clientSecret", "client_secret_value");
|
||||
ReflectionTestUtils.setField(target, "igdbApiBaseUrl", "http://localhost:%s".formatted(igdbApiMock.getPort()));
|
||||
ReflectionTestUtils.setField(target, "twitchAuthUrl", "http://localhost:%s/oauth2/token".formatted(twitchApiMock.getPort()));
|
||||
ReflectionTestUtils.setField(target, "preferredPlatforms", List.of(6));
|
||||
|
||||
when(gameyfinPropertiesMock.igdb().config().preferredPlatforms()).thenReturn(List.of(6));
|
||||
|
||||
when(webClientConfigMock.getIgdbConcurrencyLimiter()).thenReturn(Bulkhead.of("test_bulkhead", BulkheadConfig.ofDefaults()));
|
||||
when(webClientConfigMock.getIgdbRateLimiter()).thenReturn(RateLimiter.of("test_ratelimiter", RateLimiterConfig.ofDefaults()));
|
||||
|
||||
@@ -4,6 +4,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Named.named;
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystem;
|
||||
@@ -13,6 +15,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import de.grimsi.gameyfin.config.properties.GameyfinProperties;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
@@ -24,6 +27,7 @@ import com.google.common.jimfs.Jimfs;
|
||||
|
||||
class FilenameUtilTest {
|
||||
|
||||
private static final GameyfinProperties gameyfinPropertiesMock = mock(GameyfinProperties.class);
|
||||
private static final FileSystem unixFS = Jimfs.newFileSystem(Configuration.unix());
|
||||
private static final FileSystem osxFS = Jimfs.newFileSystem(Configuration.osX());
|
||||
private static final FileSystem winFS = Jimfs.newFileSystem(Configuration.windows());
|
||||
@@ -33,9 +37,10 @@ class FilenameUtilTest {
|
||||
|
||||
@BeforeAll
|
||||
static void init() {
|
||||
FilenameUtil filenameUtil = new FilenameUtil();
|
||||
filenameUtil.setPossibleGameFileExtensions(gameFileExtensions);
|
||||
filenameUtil.setPossibleGameFileSuffixes(possibleGameFileSuffixes);
|
||||
when(gameyfinPropertiesMock.fileExtensions()).thenReturn(gameFileExtensions);
|
||||
when(gameyfinPropertiesMock.fileSuffixes()).thenReturn(possibleGameFileSuffixes);
|
||||
|
||||
FilenameUtil filenameUtil = new FilenameUtil(gameyfinPropertiesMock);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
|
||||
Reference in New Issue
Block a user