@@ -20,15 +20,14 @@ import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/** Manages game metadata stored as JSON files on disk. */
|
||||
@ApplicationScoped
|
||||
public class GameService implements GameStore {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(GameService.class.getName());
|
||||
|
||||
private final ObjectMapper mapper = new ObjectMapper()
|
||||
.registerModule(new JavaTimeModule())
|
||||
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
|
||||
@@ -121,7 +120,7 @@ public class GameService implements GameStore {
|
||||
}
|
||||
|
||||
/** Delete a game and all its files. */
|
||||
public boolean delete(String id) throws IOException {
|
||||
public void delete(String id) throws IOException {
|
||||
Path dir = gameDir(id);
|
||||
if (Files.exists(dir)) {
|
||||
Files.walkFileTree(dir, new SimpleFileVisitor<>() {
|
||||
@@ -140,7 +139,6 @@ public class GameService implements GameStore {
|
||||
// Clean up old flat .jsdos locations (pre-game-dir layout — backward compat)
|
||||
Files.deleteIfExists(gamesDir.resolve(id + ".jsdos"));
|
||||
Files.deleteIfExists(gamesDir.resolve(id + ".setup.jsdos"));
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Sanitize a string for use as a game directory ID. */
|
||||
|
||||
@@ -13,7 +13,7 @@ public interface GameStore {
|
||||
Game load(String id) throws IOException, NoSuchFileException;
|
||||
void save(Game game) throws IOException;
|
||||
List<Game> list() throws IOException;
|
||||
boolean delete(String id) throws IOException;
|
||||
void delete(String id) throws IOException;
|
||||
Path gameDir(String id);
|
||||
Path gameJsonPath(String id);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DefaultValue;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
@@ -13,7 +14,7 @@ import jakarta.ws.rs.core.Response;
|
||||
import java.util.Map;
|
||||
|
||||
/** IGDB metadata & artwork integration. Enabled when TWITCH_CLIENT_ID and TWITCH_CLIENT_SECRET are set. */
|
||||
@jakarta.ws.rs.Path("/api/igdb")
|
||||
@Path("/api/igdb")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class IgdbController {
|
||||
|
||||
@@ -24,7 +25,7 @@ public class IgdbController {
|
||||
GameService games;
|
||||
|
||||
@GET
|
||||
@jakarta.ws.rs.Path("/search")
|
||||
@Path("/search")
|
||||
public Response search(@QueryParam("q") @DefaultValue("") String query) {
|
||||
if (query.isBlank()) {
|
||||
return Response.status(400).entity(Map.of("error", "Query parameter 'q' is required")).build();
|
||||
@@ -45,7 +46,7 @@ public class IgdbController {
|
||||
* Body: {} — auto-search using the game's title.
|
||||
*/
|
||||
@POST
|
||||
@jakarta.ws.rs.Path("/scrape/{gameId}")
|
||||
@Path("/scrape/{gameId}")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response scrape(@PathParam("gameId") String gameId, Map<String, Object> body) {
|
||||
try {
|
||||
@@ -72,7 +73,7 @@ public class IgdbController {
|
||||
|
||||
/** Check if IGDB credentials are configured. */
|
||||
@GET
|
||||
@jakarta.ws.rs.Path("/status")
|
||||
@Path("/status")
|
||||
public Response status() {
|
||||
boolean configured = svc.isConfigured();
|
||||
return Response.ok(Map.of(
|
||||
|
||||
Reference in New Issue
Block a user