Public Access
Add owned-games DTO and full profile support
Introduce SteamOwnedGamesResponse and SteamProfileAndGamesResponse DTOs and extend SteamApiService with getOwnedGames(...) and getFullPlayerProfile(...) to fetch and combine player summary and owned games. Update SteamTestController to return the combined profile/games response. Remove redundant Steam service URL entries from application.yml. Add SteamApiServiceTest to cover player summary, owned games (including null fields), and the combined profile flow; service falls back to empty lists on errors.
This commit is contained in:
1 parent
1dc2efba01
commit
be9b70c541
6 files changed
+243
-6
No files matched your search
@@ -1,6 +1,6 @@
|
||||
package core_service.modules.steam_adapter.api;
|
||||
|
||||
import core_service.modules.steam_adapter.api.dto.response.SteamPlayerSummaryResponse;
|
||||
import core_service.modules.steam_adapter.api.dto.response.SteamProfileAndGamesResponse;
|
||||
import core_service.modules.steam_adapter.service.SteamApiService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -21,10 +21,10 @@ public class SteamTestController {
|
||||
@GetMapping("/{steamId}")
|
||||
public ResponseEntity<?> testSteamConnection(@PathVariable String steamId) {
|
||||
|
||||
Optional<SteamPlayerSummaryResponse.Player> playerOpt = steamApiService.getPlayerSummary(steamId);
|
||||
Optional<SteamProfileAndGamesResponse> profileOpt = steamApiService.getFullPlayerProfile(steamId);
|
||||
|
||||
if (playerOpt.isPresent()) {
|
||||
return ResponseEntity.ok(playerOpt.get());
|
||||
if (profileOpt.isPresent()) {
|
||||
return ResponseEntity.ok(profileOpt.get());
|
||||
} else {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package core_service.modules.steam_adapter.api.dto.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import java.util.List;
|
||||
|
||||
public record SteamOwnedGamesResponse(OwnedGamesResponse response) {
|
||||
|
||||
public record OwnedGamesResponse(
|
||||
@JsonProperty("game_count") int gameCount,
|
||||
List<Game> games
|
||||
) {}
|
||||
|
||||
public record Game(
|
||||
Integer appid,
|
||||
String name,
|
||||
@JsonProperty("playtime_forever") Integer playtimeForever,
|
||||
@JsonProperty("img_icon_url") String imgIconUrl,
|
||||
@JsonProperty("has_community_visible_stats") Boolean hasCommunityVisibleStats
|
||||
) {}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package core_service.modules.steam_adapter.api.dto.response;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record SteamProfileAndGamesResponse(
|
||||
SteamPlayerSummaryResponse.Player player,
|
||||
List<SteamOwnedGamesResponse.Game> games
|
||||
) {
|
||||
}
|
||||
@@ -1,12 +1,16 @@
|
||||
package core_service.modules.steam_adapter.service;
|
||||
|
||||
import core_service.modules.steam_adapter.api.dto.response.SteamOwnedGamesResponse;
|
||||
import core_service.modules.steam_adapter.api.dto.response.SteamPlayerSummaryResponse;
|
||||
import core_service.modules.steam_adapter.api.dto.response.SteamProfileAndGamesResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
@@ -19,6 +23,16 @@ public class SteamApiService {
|
||||
@Value("${app.steam.api-key}")
|
||||
private String apiKey;
|
||||
|
||||
public Optional<SteamProfileAndGamesResponse> getFullPlayerProfile(String steamId) {
|
||||
var playerOpt = getPlayerSummary(steamId);
|
||||
if (playerOpt.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
var games = getOwnedGames(steamId);
|
||||
return Optional.of(new SteamProfileAndGamesResponse(playerOpt.get(), games));
|
||||
}
|
||||
|
||||
public Optional<SteamPlayerSummaryResponse.Player> getPlayerSummary(String steamId) {
|
||||
try {
|
||||
log.info("Fetching Steam profile for SteamID: {}", steamId);
|
||||
@@ -42,4 +56,30 @@ public class SteamApiService {
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public List<SteamOwnedGamesResponse.Game> getOwnedGames(String steamId) {
|
||||
try {
|
||||
log.info("Fetching owned games for SteamID: {}", steamId);
|
||||
|
||||
SteamOwnedGamesResponse response = steamRestClient.get()
|
||||
.uri(uriBuilder -> uriBuilder
|
||||
.path("/IPlayerService/GetOwnedGames/v0001/")
|
||||
.queryParam("key", apiKey)
|
||||
.queryParam("steamid", steamId)
|
||||
.queryParam("include_appinfo", 1)
|
||||
.queryParam("include_played_free_games", 1)
|
||||
.build())
|
||||
.retrieve()
|
||||
.body(SteamOwnedGamesResponse.class);
|
||||
|
||||
if (response != null && response.response() != null && response.response().games() != null) {
|
||||
return response.response().games();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Error communicating with Steam API for games of SteamID: {}", steamId, e);
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,4 @@ app:
|
||||
steam:
|
||||
api-key: ${STEAM_API_KEY}
|
||||
base-url: https://api.steampowered.com
|
||||
playerService-url: https://api.steampowered.com/IPlayerService/GetOwnedGames/v1/
|
||||
storeService-url: https://api.steampowered.com/IStoreService/GetAppList/v1/
|
||||
imageService-url: https://cdn.cloudflare.steamstatic.com/steam/apps/
|
||||
@@ -0,0 +1,170 @@
|
||||
package core_service.modules.steam_adapter.service;
|
||||
|
||||
import core_service.modules.steam_adapter.api.dto.response.SteamOwnedGamesResponse;
|
||||
import core_service.modules.steam_adapter.api.dto.response.SteamPlayerSummaryResponse;
|
||||
import core_service.modules.steam_adapter.api.dto.response.SteamProfileAndGamesResponse;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.queryParam;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||
|
||||
class SteamApiServiceTest {
|
||||
|
||||
private SteamApiService steamApiService;
|
||||
private MockRestServiceServer server;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
RestClient.Builder builder = RestClient.builder();
|
||||
server = MockRestServiceServer.bindTo(builder).build();
|
||||
steamApiService = new SteamApiService(builder.build());
|
||||
ReflectionTestUtils.setField(steamApiService, "apiKey", "test-api-key");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPlayerSummary_shouldReturnPlayer() {
|
||||
String steamId = "76561197960435530";
|
||||
String jsonResponse = """
|
||||
{
|
||||
"response": {
|
||||
"players": [
|
||||
{
|
||||
"steamid": "76561197960435530",
|
||||
"personaname": "TestUser",
|
||||
"profileurl": "http://steamcommunity.com/id/testuser/",
|
||||
"avatarfull": "http://media.steampowered.com/avatar.jpg"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
server.expect(requestTo(containsString("/ISteamUser/GetPlayerSummaries/v0002/")))
|
||||
.andExpect(queryParam("steamids", steamId))
|
||||
.andExpect(queryParam("key", "test-api-key"))
|
||||
.andRespond(withSuccess(jsonResponse, MediaType.APPLICATION_JSON));
|
||||
|
||||
Optional<SteamPlayerSummaryResponse.Player> result = steamApiService.getPlayerSummary(steamId);
|
||||
|
||||
assertThat(result).isPresent();
|
||||
assertThat(result.get().personaname()).isEqualTo("TestUser");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getOwnedGames_shouldReturnGames() {
|
||||
String steamId = "76561197960435530";
|
||||
String jsonResponse = """
|
||||
{
|
||||
"response": {
|
||||
"game_count": 1,
|
||||
"games": [
|
||||
{
|
||||
"appid": 10,
|
||||
"name": "Counter-Strike",
|
||||
"playtime_forever": 32,
|
||||
"img_icon_url": "icon_url",
|
||||
"has_community_visible_stats": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
server.expect(requestTo(containsString("/IPlayerService/GetOwnedGames/v0001/")))
|
||||
.andExpect(queryParam("steamid", steamId))
|
||||
.andExpect(queryParam("key", "test-api-key"))
|
||||
.andRespond(withSuccess(jsonResponse, MediaType.APPLICATION_JSON));
|
||||
|
||||
List<SteamOwnedGamesResponse.Game> result = steamApiService.getOwnedGames(steamId);
|
||||
|
||||
assertThat(result).hasSize(1);
|
||||
assertThat(result.get(0).name()).isEqualTo("Counter-Strike");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getOwnedGames_shouldReturnGamesEvenWithNullValues() {
|
||||
String steamId = "76561197960435530";
|
||||
String jsonResponse = """
|
||||
{
|
||||
"response": {
|
||||
"game_count": 1,
|
||||
"games": [
|
||||
{
|
||||
"appid": 10,
|
||||
"name": "Counter-Strike"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
server.expect(requestTo(containsString("/IPlayerService/GetOwnedGames/v0001/")))
|
||||
.andRespond(withSuccess(jsonResponse, MediaType.APPLICATION_JSON));
|
||||
|
||||
List<SteamOwnedGamesResponse.Game> result = steamApiService.getOwnedGames(steamId);
|
||||
|
||||
assertThat(result).hasSize(1);
|
||||
assertThat(result.get(0).name()).isEqualTo("Counter-Strike");
|
||||
assertThat(result.get(0).playtimeForever()).isNull();
|
||||
assertThat(result.get(0).hasCommunityVisibleStats()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFullPlayerProfile_shouldReturnCombinedResult() {
|
||||
String steamId = "76561197960435530";
|
||||
String summaryJson = """
|
||||
{
|
||||
"response": {
|
||||
"players": [
|
||||
{
|
||||
"steamid": "76561197960435530",
|
||||
"personaname": "TestUser",
|
||||
"profileurl": "url",
|
||||
"avatarfull": "avatar"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""";
|
||||
String gamesJson = """
|
||||
{
|
||||
"response": {
|
||||
"game_count": 1,
|
||||
"games": [
|
||||
{
|
||||
"appid": 10,
|
||||
"name": "Counter-Strike",
|
||||
"playtime_forever": 32,
|
||||
"img_icon_url": "icon_url",
|
||||
"has_community_visible_stats": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
server.expect(requestTo(containsString("/ISteamUser/GetPlayerSummaries/v0002/")))
|
||||
.andRespond(withSuccess(summaryJson, MediaType.APPLICATION_JSON));
|
||||
|
||||
server.expect(requestTo(containsString("/IPlayerService/GetOwnedGames/v0001/")))
|
||||
.andRespond(withSuccess(gamesJson, MediaType.APPLICATION_JSON));
|
||||
|
||||
Optional<SteamProfileAndGamesResponse> result = steamApiService.getFullPlayerProfile(steamId);
|
||||
|
||||
assertThat(result).isPresent();
|
||||
assertThat(result.get().player().personaname()).isEqualTo("TestUser");
|
||||
assertThat(result.get().games()).hasSize(1);
|
||||
assertThat(result.get().games().get(0).name()).isEqualTo("Counter-Strike");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user