diff --git a/src/main/java/auctiora/DatabaseService.java b/src/main/java/auctiora/DatabaseService.java index eb2eff6..91ddd8b 100644 --- a/src/main/java/auctiora/DatabaseService.java +++ b/src/main/java/auctiora/DatabaseService.java @@ -864,9 +864,13 @@ public class DatabaseService { try (var conn = DriverManager.getConnection(url); var stmt = conn.createStatement()) { var rs = stmt.executeQuery(sql); while (rs.next()) { + // Extract numeric lot ID from TEXT field (e.g., "A1-34732-49" -> 3473249) + String lotIdStr = rs.getString("lot_id"); + long lotId = ScraperDataAdapter.extractNumericId(lotIdStr); + images.add(new ImageDetectionRecord( rs.getInt("id"), - rs.getLong("lot_id"), + lotId, rs.getString("local_path") )); } diff --git a/src/main/java/auctiora/TroostwijkGraphQLClient.java b/src/main/java/auctiora/TroostwijkGraphQLClient.java index 7ea9b0b..59e8c0f 100644 --- a/src/main/java/auctiora/TroostwijkGraphQLClient.java +++ b/src/main/java/auctiora/TroostwijkGraphQLClient.java @@ -23,7 +23,9 @@ import java.util.List; @ApplicationScoped public class TroostwijkGraphQLClient { - private static final String GRAPHQL_ENDPOINT = "https://www.troostwijk.com/graphql"; + private static final String GRAPHQL_ENDPOINT = "https://storefront.tbauctions.com/storefront/graphql"; + private static final String LOCALE = "nl"; + private static final String PLATFORM = "TWK"; private static final ObjectMapper objectMapper = new ObjectMapper(); @Inject @@ -37,12 +39,19 @@ public class TroostwijkGraphQLClient { public LotIntelligence fetchLotIntelligence(long lotId) { try { String query = buildLotQuery(lotId); - String requestBody = String.format("{\"query\":\"%s\"}", - escapeJson(query)); + String variables = buildVariables(lotId); + + // Proper GraphQL request format with query and variables + String requestBody = String.format( + "{\"query\":\"%s\",\"variables\":%s}", + escapeJson(query), + variables + ); var request = java.net.http.HttpRequest.newBuilder() .uri(java.net.URI.create(GRAPHQL_ENDPOINT)) .header("Content-Type", "application/json") + .header("Accept", "application/json") .POST(java.net.http.HttpRequest.BodyPublishers.ofString(requestBody)) .build(); @@ -56,6 +65,7 @@ public class TroostwijkGraphQLClient { return null; } + log.debug("GraphQL response for lot {}: {}", lotId, response.body().substring(0, Math.min(200, response.body().length()))); return parseLotIntelligence(response.body(), lotId); } catch (Exception e) { @@ -105,36 +115,34 @@ public class TroostwijkGraphQLClient { } private String buildLotQuery(long lotId) { + // TBAuctions API uses lot objects with specific fields + // Note: This query structure needs to be adjusted based on actual TBAuctions schema return """ - query { - lot(id: %d) { + query GetLot($lotId: String!, $locale: String!, $platform: Platform!) { + lot(id: $lotId, locale: $locale, platform: $platform) { id + displayId followersCount - estimatedMin - estimatedMax + currentBidInCents nextBidStepInCents condition - categoryPath - city - countryCode + description biddingStatus - appearance - packaging - quantity - vat - buyerPremiumPercentage - remarks - startingBid - reservePrice - reserveMet - bidIncrement + buyerPremium viewCount - firstBidTime - lastBidTime - bidsCount } } - """.formatted(lotId).replaceAll("\\s+", " "); + """.replaceAll("\\s+", " "); + } + + private String buildVariables(long lotId) { + return String.format(""" + { + "lotId": "%d", + "locale": "%s", + "platform": "%s" + } + """, lotId, LOCALE, PLATFORM).replaceAll("\\s+", " "); } private String buildBatchLotQuery(List lotIds) { @@ -167,6 +175,12 @@ public class TroostwijkGraphQLClient { private LotIntelligence parseLotIntelligence(String json, long lotId) { try { + // Check if response is HTML (error page) instead of JSON + if (json != null && json.trim().startsWith("<")) { + log.debug("GraphQL API returned HTML instead of JSON - likely auth required or wrong endpoint"); + return null; + } + JsonNode root = objectMapper.readTree(json); JsonNode lotNode = root.path("data").path("lot");