mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-15 16:20:03 +00:00
+1
-1
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>gameyfin</artifactId>
|
<artifactId>gameyfin</artifactId>
|
||||||
<groupId>de.grimsi</groupId>
|
<groupId>de.grimsi</groupId>
|
||||||
<version>1.1.1</version>
|
<version>1.1.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>gameyfin-backend</artifactId>
|
<artifactId>gameyfin-backend</artifactId>
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import java.nio.file.FileSystem;
|
|||||||
import java.nio.file.FileSystems;
|
import java.nio.file.FileSystems;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@@ -53,6 +54,7 @@ public class GameMapper {
|
|||||||
.playerPerspectives(PlayerPerspectiveMapper.toPlayerPerspectives(g.getPlayerPerspectivesList()))
|
.playerPerspectives(PlayerPerspectiveMapper.toPlayerPerspectives(g.getPlayerPerspectivesList()))
|
||||||
.path(path.toString())
|
.path(path.toString())
|
||||||
.diskSize(calculateDiskSize(g, path))
|
.diskSize(calculateDiskSize(g, path))
|
||||||
|
.addedToLibrary(Instant.now())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ public class DownloadService {
|
|||||||
|
|
||||||
MultiValueMap<String, String> gameToImageIds = new LinkedMultiValueMap<>(
|
MultiValueMap<String, String> gameToImageIds = new LinkedMultiValueMap<>(
|
||||||
detectedGameRepository.findAll().stream()
|
detectedGameRepository.findAll().stream()
|
||||||
.collect(Collectors.toMap(DetectedGame::getTitle, g -> Collections.singletonList(g.getCoverId()))));
|
.collect(Collectors.toMap(DetectedGame::getSlug, g -> Collections.singletonList(g.getCoverId()))));
|
||||||
|
|
||||||
int downloadCount = downloadImagesIntoCache(gameToImageIds, IgdbApiProperties.COVER_IMAGE_SIZE, "cover", "game");
|
int downloadCount = downloadImagesIntoCache(gameToImageIds, IgdbApiProperties.COVER_IMAGE_SIZE, "cover", "game");
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ public class DownloadService {
|
|||||||
|
|
||||||
MultiValueMap<String, String> gamesToImageIds = new LinkedMultiValueMap<>(
|
MultiValueMap<String, String> gamesToImageIds = new LinkedMultiValueMap<>(
|
||||||
detectedGameRepository.findAll().stream()
|
detectedGameRepository.findAll().stream()
|
||||||
.collect(Collectors.toMap(DetectedGame::getTitle, DetectedGame::getScreenshotIds)));
|
.collect(Collectors.toMap(DetectedGame::getSlug, DetectedGame::getScreenshotIds)));
|
||||||
|
|
||||||
int downloadCount = downloadImagesIntoCache(gamesToImageIds, IgdbApiProperties.SCREENSHOT_IMAGE_SIZE, "screenshot", "game");
|
int downloadCount = downloadImagesIntoCache(gamesToImageIds, IgdbApiProperties.SCREENSHOT_IMAGE_SIZE, "screenshot", "game");
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ public class DownloadService {
|
|||||||
|
|
||||||
Map<String, List<String>> companyToLogoIdMap = detectedGameRepository.findAll().stream()
|
Map<String, List<String>> companyToLogoIdMap = detectedGameRepository.findAll().stream()
|
||||||
.flatMap(g -> g.getCompanies().stream())
|
.flatMap(g -> g.getCompanies().stream())
|
||||||
.collect(Collectors.toMap(Company::getName, c -> Collections.singletonList(c.getLogoId()), (c1, c2) -> c1));
|
.collect(Collectors.toMap(Company::getSlug, c -> Collections.singletonList(c.getLogoId()), (c1, c2) -> c1));
|
||||||
|
|
||||||
MultiValueMap<String, String> companiesToLogoIds = new LinkedMultiValueMap<>(companyToLogoIdMap);
|
MultiValueMap<String, String> companiesToLogoIds = new LinkedMultiValueMap<>(companyToLogoIdMap);
|
||||||
|
|
||||||
@@ -215,12 +215,24 @@ public class DownloadService {
|
|||||||
String imgUrl = "t_%s/%s".formatted(imageSize, imgFileName);
|
String imgUrl = "t_%s/%s".formatted(imageSize, imgFileName);
|
||||||
|
|
||||||
if (Files.exists(Path.of(cacheFolderPath, imgFileName))) {
|
if (Files.exists(Path.of(cacheFolderPath, imgFileName))) {
|
||||||
log.debug("{} for {} '{}' already downloaded ({}), skipping.",
|
|
||||||
imageType.substring(0, 1).toUpperCase() + imageType.substring(1).toLowerCase(),
|
Path existingImageFile = Path.of(cacheFolderPath, imgFileName);
|
||||||
entityType,
|
|
||||||
entry.getKey(),
|
try {
|
||||||
imgFileName);
|
if(Files.size(existingImageFile) == 0L) {
|
||||||
return;
|
log.info("File '{}' is corrupt, retrying download...", imgFileName);
|
||||||
|
Files.delete(existingImageFile);
|
||||||
|
} else {
|
||||||
|
log.debug("{} for {} '{}' already downloaded ({}), skipping.",
|
||||||
|
imageType.substring(0, 1).toUpperCase() + imageType.substring(1).toLowerCase(),
|
||||||
|
entityType,
|
||||||
|
entry.getKey(),
|
||||||
|
imgFileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error while checking file '{}'.", existingImageFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Flux<DataBuffer> dataBuffer = igdbImageClient.get()
|
Flux<DataBuffer> dataBuffer = igdbImageClient.get()
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static de.grimsi.gameyfin.util.FilenameUtil.getFilenameWithoutExtension;
|
import static de.grimsi.gameyfin.util.FilenameUtil.getFilenameWithoutExtension;
|
||||||
@@ -83,11 +84,17 @@ public class LibraryService {
|
|||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
// For each new game, load the info from IGDB
|
// For each new game, load the info from IGDB
|
||||||
// If a game is not found on IGDB, add it to the list of unmapped files so we won't query the API later on for the same path
|
// If a game is not found on IGDB, add it to the list of unmapped files, so we won't query the API later on for the same path
|
||||||
// If a game is not found on IGDB, blacklist the path, so we won't query the API later for the same path
|
// If a game is not found on IGDB, blacklist the path, so we won't query the API later for the same path
|
||||||
List<DetectedGame> newDetectedGames = gameFiles.parallelStream()
|
List<DetectedGame> newDetectedGames = gameFiles.parallelStream()
|
||||||
.map(p -> {
|
.map(p -> {
|
||||||
Optional<Igdb.Game> optionalGame = igdbWrapper.searchForGameByTitle(getFilenameWithoutExtension(p));
|
Optional<Igdb.Game> optionalGame = igdbWrapper.searchForGameByTitle(getFilenameWithoutExtension(p));
|
||||||
|
|
||||||
|
if(optionalGame.isPresent() && detectedGameRepository.existsBySlug(optionalGame.get().getSlug())) {
|
||||||
|
log.warn("Game with slug '{}' already exists in database", optionalGame.get().getSlug());
|
||||||
|
optionalGame = Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
return optionalGame.map(game -> Map.entry(p, game)).or(() -> {
|
return optionalGame.map(game -> Map.entry(p, game)).or(() -> {
|
||||||
unmappableFileRepository.save(new UnmappableFile(p.toString()));
|
unmappableFileRepository.save(new UnmappableFile(p.toString()));
|
||||||
newUnmappedFilesCounter.getAndIncrement();
|
newUnmappedFilesCounter.getAndIncrement();
|
||||||
@@ -99,7 +106,11 @@ public class LibraryService {
|
|||||||
.map(Optional::get)
|
.map(Optional::get)
|
||||||
.peek(e -> log.info("Mapped file '{}' to game '{}' (slug: {})", e.getKey(), e.getValue().getName(), e.getValue().getSlug()))
|
.peek(e -> log.info("Mapped file '{}' to game '{}' (slug: {})", e.getKey(), e.getValue().getName(), e.getValue().getSlug()))
|
||||||
.map(e -> GameMapper.toDetectedGame(e.getValue(), e.getKey()))
|
.map(e -> GameMapper.toDetectedGame(e.getValue(), e.getKey()))
|
||||||
.toList();
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
List<DetectedGame> duplicateGames = getDuplicates(newDetectedGames);
|
||||||
|
newUnmappedFilesCounter.getAndAdd(duplicateGames.size());
|
||||||
|
newDetectedGames.removeAll(duplicateGames);
|
||||||
|
|
||||||
newDetectedGames = detectedGameRepository.saveAll(newDetectedGames);
|
newDetectedGames = detectedGameRepository.saveAll(newDetectedGames);
|
||||||
|
|
||||||
@@ -112,4 +123,13 @@ public class LibraryService {
|
|||||||
public List<AutocompleteSuggestionDto> getAutocompleteSuggestions(String searchTerm, int limit) {
|
public List<AutocompleteSuggestionDto> getAutocompleteSuggestions(String searchTerm, int limit) {
|
||||||
return igdbWrapper.findPossibleMatchingTitles(searchTerm, limit);
|
return igdbWrapper.findPossibleMatchingTitles(searchTerm, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<DetectedGame> getDuplicates(List<DetectedGame> gamesToFilter) {
|
||||||
|
return gamesToFilter.stream().filter(g -> Collections.frequency(gamesToFilter, g) >1)
|
||||||
|
.peek(d -> {
|
||||||
|
log.warn("Found duplicate for game '{}' under path '{}'. Mapping must be done manually.", d.getTitle(), d.getPath());
|
||||||
|
unmappableFileRepository.save(new UnmappableFile(d.getPath()));
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>gameyfin</artifactId>
|
<artifactId>gameyfin</artifactId>
|
||||||
<groupId>de.grimsi</groupId>
|
<groupId>de.grimsi</groupId>
|
||||||
<version>1.1.1</version>
|
<version>1.1.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<groupId>de.grimsi</groupId>
|
<groupId>de.grimsi</groupId>
|
||||||
<artifactId>gameyfin</artifactId>
|
<artifactId>gameyfin</artifactId>
|
||||||
<version>1.1.1</version>
|
<version>1.1.2</version>
|
||||||
<name>gameyfin</name>
|
<name>gameyfin</name>
|
||||||
<description>gameyfin</description>
|
<description>gameyfin</description>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user