Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion PlaylistApp.Server/Controllers/SteamController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public SteamController(ISteamService steamService, ISteamOrchestrator steamOrche
}

[HttpPost("getuseractionlog")]
public async Task<ItemAction> GetGamesBySteamId([FromBody] SteamActionLogRequest steamActionLogRequest)
public async Task<List<ItemAction>> GetGamesBySteamId([FromBody] SteamActionLogRequest steamActionLogRequest)
{
return await steamOrchestrator.CollectActionItemsFromSteam(steamActionLogRequest);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ namespace PlaylistApp.Server.Services.SteamServices
{
public interface ISteamOrchestrator
{
Task<ItemAction> CollectActionItemsFromSteam(SteamActionLogRequest steamActionLogRequest);
Task<List<ItemAction>> CollectActionItemsFromSteam(SteamActionLogRequest steamActionLogRequest);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
using IGDB.Models;
using Microsoft.EntityFrameworkCore;
using NSubstitute;
using Microsoft.EntityFrameworkCore;
using PlaylistApp.Server.Data;
using PlaylistApp.Server.DTOs.SteamData.SteamAchievements;
using PlaylistApp.Server.DTOs.SteamData.SteamGames;
using PlaylistApp.Server.Requests.AddRequests;
using PlaylistApp.Server.Services.IGDBServices;
using PlaylistApp.Server.Services.SteamServices.SteamAchievementService.SteamAchievementService;
using PlaylistApp.Server.Services.UserAchievementServices;
using System.Security.Cryptography;

namespace PlaylistApp.Server.Services.SteamServices.SteamAchievementService;

Expand Down Expand Up @@ -40,38 +35,48 @@ public async Task AddMissingAchievementsToUser(Guid userId, string steamId)
}

var userPlatformGames = await context.UserGames.Where(x => x.UserId == user.Id).Include(x => x.PlatformGame).ToListAsync();
HashSet<int> userPlatformGameIds = new(userPlatformGames.Select(x => x.PlatformGameId));
List<string> userPgsPlatformKeys = new(userPlatformGames.Select(x => x.PlatformGame.PlatformKey ?? string.Empty));

List<PlayerStatsResponse> playerStatsResponse = await GetAllSteamAchievements(userPgsPlatformKeys, steamId);

var userAchievements = await context.UserAchievements.Where(x => x.UserId == user.Id).Include(a => a.Achievement).ThenInclude(pg => pg.PlatformGame).ToListAsync();

AddMultipleUserAchievementRequest AddAchievementsRequest = new();
AddAchievementsRequest.UserGuid = userId;

try
{
var allPlatformGameAchievements = await context.Achievements
.Where(a => userPlatformGameIds.Contains(a.PlatformGameId))
.ToListAsync();
foreach (var pg in userPlatformGames)
{
if (pg.PlatformGame.PlatformKey is not null)
{
string url = $"https://api.steampowered.com/ISteamUserStats/GetPlayerAchievements/v0001/?appid={pg.PlatformGame.PlatformKey}&key={steamKey}&steamid={steamId}";
HttpResponseMessage response = await client.GetAsync(url);

PlayerStatsResponse jsonResponse = await response.Content.ReadFromJsonAsync<PlayerStatsResponse>() ?? new PlayerStatsResponse();

foreach (var ach in jsonResponse.PlayerStats.Achievements)
foreach (var jsonResponse in playerStatsResponse)
{
var matchingAch = userAchievements.Where(x => x.Achievement.ExternalId == ach.Apiname).Where(x => x.Achievement.PlatformGame.Id == pg.Id).FirstOrDefault();
if (ach.Achieved == 1 && matchingAch is null)
foreach (var ach in jsonResponse.PlayerStats.Achievements)
{
var projectPlaylistAchievement = await context.Achievements.Where(x => x.PlatformGameId == pg.PlatformGameId && x.ExternalId == ach.Apiname).FirstOrDefaultAsync();
if (projectPlaylistAchievement is not null)
var matchingAch = userAchievements.Where(x => x.Achievement.ExternalId == ach.Apiname).Where(x => x.Achievement.PlatformGame.Id == pg.Id).FirstOrDefault();
if (ach.Achieved == 1 && matchingAch is null)
{
AddUserAchievementRequest request = new()
//var projectPlaylistAchievement = await context.Achievements.Where(x => x.PlatformGameId == pg.PlatformGameId && x.ExternalId == ach.Apiname).FirstOrDefaultAsync(); // Make this line faster and maybe not use the context every time

var projectPlaylistAchievement = allPlatformGameAchievements
.FirstOrDefault(x => x.PlatformGameId == pg.PlatformGameId && x.ExternalId == ach.Apiname);

if (projectPlaylistAchievement is not null)
{
UserGuid = userId,
IsSelfSubmitted = false,
DateAchieved = Conversions.UnixTimeToDateTime(ach.UnlockTime),
AchievementId = projectPlaylistAchievement.Id,
};
AddAchievementsRequest.UserAchievementRequests.Add(request);
AddUserAchievementRequest request = new()
{
UserGuid = userId,
IsSelfSubmitted = false,
DateAchieved = Conversions.UnixTimeToDateTime(ach.UnlockTime),
AchievementId = projectPlaylistAchievement.Id,
};
AddAchievementsRequest.UserAchievementRequests.Add(request);
}
}
}
}
Expand All @@ -84,4 +89,20 @@ public async Task AddMissingAchievementsToUser(Guid userId, string steamId)
throw new Exception("An Error occured when fetching achievements from Steam: " + e.Message);
}
}

public async Task<List<PlayerStatsResponse>> GetAllSteamAchievements(List<string> userPgsPlatformKeys, string steamId)
{
List<PlayerStatsResponse> responses = new();

var steamKey = config["steamkey"];
foreach (var key in userPgsPlatformKeys)
{
string url = $"https://api.steampowered.com/ISteamUserStats/GetPlayerAchievements/v0001/?appid={key}&key={steamKey}&steamid={steamId}";
HttpResponseMessage response = await client.GetAsync(url);

responses.Add(await response.Content.ReadFromJsonAsync<PlayerStatsResponse>() ?? new PlayerStatsResponse());
}

return responses;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ public interface ISteamService
public Task<OwnedGamesResponse> GetGamesFromUserBasedOffOfSteamId(string steamId);
public Task<List<PlatformGame>> ConvertSteamToPlatformGames(OwnedGamesResponse jsonResponse);

public Task<ItemAction> FindGameInconsistenciesWithUserAccount(List<PlatformGame> matchingPlatformGames, List<SteamRawGame> steamGames, Guid userGuid);
public Task<List<ItemAction>> FindGameInconsistenciesWithUserAccount(List<PlatformGame> matchingPlatformGames, List<SteamRawGame> steamGames, Guid userGuid);

public Task AddMissingGamesToUserGames(OwnedGamesResponse response, Guid userGuid);
public Task<ItemAction> FixTimeDifferences(OwnedGamesResponse response, List<PlatformGame> matchingPlatformGames, List<SteamRawGame> steamGames, Guid userGuid);
public Task<List<ItemAction>> FixTimeDifferences(OwnedGamesResponse response, List<PlatformGame> matchingPlatformGames, List<SteamRawGame> steamGames, Guid userGuid);
public string ExtractSteamIdFromUrl(string urlParams);
public void AddSteamKeyToUser(string userId, string steamId);
public Task AddSteamUsernameToUser(string userGuid, string steamId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,8 @@ public async Task<List<PlatformGame>> ConvertSteamToPlatformGames(OwnedGamesResp
return matchingPlatformGames;
}

public async Task<ItemAction> FindGameInconsistenciesWithUserAccount(List<PlatformGame> matchingPlatformGames, List<SteamRawGame> steamGames, Guid userId)
public async Task<List<ItemAction>> FindGameInconsistenciesWithUserAccount(List<PlatformGame> matchingPlatformGames, List<SteamRawGame> steamGames, Guid userId)
{
ItemAction action = new();
using var context = await dbContextFactory.CreateDbContextAsync();

var duplicatePlatformKeys = matchingPlatformGames
Expand All @@ -104,35 +103,52 @@ public async Task<ItemAction> FindGameInconsistenciesWithUserAccount(List<Platfo
.ThenInclude(g => g.Game)
.Include(g => g.User)
.ToList();
HashSet<int> userGameIds = new HashSet<int>(usersGames.Select(x => x.PlatformGameId));
HashSet<int> userGameIds = new(usersGames.Select(x => x.PlatformGameId));


List<ItemAction> actionsToSend = new();

int counter = 0;
string previousGame = "";
foreach (PlatformGame pg in gamesWithDuplicatePlatformKeys)

List<List<PlatformGame>> pgsGroupedByGame = gamesWithDuplicatePlatformKeys
.GroupBy(x => x.GameId)
.Select(group => group.ToList())
.ToList();

foreach (List<PlatformGame> pgGroup in pgsGroupedByGame)
{
var steamGame = steamGames.Where(x => x.AppId.ToString() == pg.PlatformKey).FirstOrDefault();
var userGameFromPlatform = usersGames.Where(x => x.PlatformGame.GameId == pg.GameId).ToList();
if (steamGame != null && !userGameFromPlatform.Any()) // if the user doesn't already have this game
ItemAction actionToAdd = new();
actionToAdd.ErrorType = $"We found multiple platforms for {pgGroup.First().Game.Title}";

foreach (var pg in pgGroup)
{
if (pg.Game.Title != previousGame)
{
counter++;
}
previousGame = pg.Game.Title;
var steamGame = steamGames.Where(x => x.AppId.ToString() == pg.PlatformKey).FirstOrDefault();
var userGameFromPlatform = usersGames.Where(x => x.PlatformGame.GameId == pg.GameId).ToList();

action.ItemOptions.Add(new ItemOption()
if (steamGame != null && !userGameFromPlatform.Any()) // if the user doesn't already have this game
{
ErrorText = pg.Platform.PlatformName,
ResolveUrl = $"/action/platforms/?hours={steamGame.PlaytimeForever}&pgid={pg.Id}&user={userId}",
GameTitle = pg.Game.Title,
Hours=steamGame.PlaytimeForever,
});

if (pg.Game.Title != previousGame)
{
counter++;
}
previousGame = pg.Game.Title;

actionToAdd.ItemOptions.Add(new ItemOption()
{
ErrorText = pg.Platform.PlatformName,
ResolveUrl = $"/action/platforms/?hours={steamGame.PlaytimeForever}&pgid={pg.Id}&user={userId}",
GameTitle = pg.Game.Title,
Hours = steamGame.PlaytimeForever,
});

}
}
actionsToSend.Add(actionToAdd);
}
action.ErrorType = "Data mismatch. Select which data is correct.";

return action;
return actionsToSend;
}

public async Task AddMissingGamesToUserGames(OwnedGamesResponse response, Guid userGuid)
Expand Down Expand Up @@ -189,9 +205,8 @@ public async Task AddMissingGamesToUserGames(OwnedGamesResponse response, Guid u
await context.SaveChangesAsync();
}

public async Task<ItemAction> FixTimeDifferences(OwnedGamesResponse response, List<PlatformGame> matchingPlatformGames, List<SteamRawGame> steamGames, Guid userGuid)
public async Task<List<ItemAction>> FixTimeDifferences(OwnedGamesResponse response, List<PlatformGame> matchingPlatformGames, List<SteamRawGame> steamGames, Guid userGuid)
{
ItemAction action = new ItemAction();

var duplicatePlatformKeys = matchingPlatformGames
.GroupBy(pg => pg.PlatformKey)
Expand All @@ -217,35 +232,43 @@ public async Task<ItemAction> FixTimeDifferences(OwnedGamesResponse response, Li
HashSet<int> userGameIds = new HashSet<int>(usersGames.Select(x => x.PlatformGameId));
int counter = 0;

List<ItemAction> actionsToSend = new();

foreach (PlatformGame pg in matchingPlatformGames)
{
UserGame? ug = usersGames.Where(x => x.PlatformGameId == pg.Id && x.UserId == userId).FirstOrDefault();
SteamRawGame? steamGame = steamGames.Where(x => x.AppId.ToString() == pg.PlatformKey).FirstOrDefault();



if (ug!.TimePlayed != steamGame?.PlaytimeForever)
{
counter++;
action.ItemOptions.Add(new ItemOption()
{
ErrorText = $"Steam record ",
ResolveUrl = $"/action/hours?hours={steamGame!.PlaytimeForever}&pgid={ug.PlatformGame.Id}&user={userGuid}",
GameTitle = ug.PlatformGame.Game.Title,
Hours = steamGame!.PlaytimeForever,
});

action.ItemOptions.Add(new ItemOption()
ItemAction action = new ItemAction()
{
ErrorText = $"Playlist record ",
ResolveUrl = $"/action/hours?hours={ug.TimePlayed}&pgid={ug.PlatformGame.Id}&user={userGuid}",
GameTitle = ug.PlatformGame.Game.Title,
Hours = (int)(ug.TimePlayed!),
});
ErrorType = "We found a difference in hours. Which hours are correct?",
ItemOptions = new List<ItemOption>
{
new ItemOption()
{
ErrorText = $"Steam record ",
ResolveUrl = $"/action/hours?hours={steamGame!.PlaytimeForever}&pgid={ug.PlatformGame.Id}&user={userGuid}",
GameTitle = ug.PlatformGame.Game.Title,
Hours = steamGame!.PlaytimeForever,
},
new ItemOption()
{
ErrorText = $"Playlist record ",
ResolveUrl = $"/action/hours?hours={ug.TimePlayed}&pgid={ug.PlatformGame.Id}&user={userGuid}",
GameTitle = ug.PlatformGame.Game.Title,
Hours = (int)(ug.TimePlayed!),
}
},
};

actionsToSend.Add(action);
}
}
action.ErrorType = "Data mismatch. Select which data is correct.";
return action;
return actionsToSend;
}

public string ExtractSteamIdFromUrl(string urlParams)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public SteamOrchestrator(ISteamService steamService, ISteamAchievementService st
this.steamAchievementService = steamAchievementService;
}

public async Task<ItemAction> CollectActionItemsFromSteam(SteamActionLogRequest steamActionLogRequest)
public async Task<List<ItemAction>> CollectActionItemsFromSteam(SteamActionLogRequest steamActionLogRequest)
{
// step 1: get all games from steam (SteamRawGames)
OwnedGamesResponse steamApiResponse = await steamService.GetGamesFromUserBasedOffOfSteamId(steamActionLogRequest.UserSteamId);
Expand All @@ -31,18 +31,18 @@ public async Task<ItemAction> CollectActionItemsFromSteam(SteamActionLogRequest
List<PlatformGame> platformGamesFromSteam = await steamService.ConvertSteamToPlatformGames(steamApiResponse);

// step 3: Check for game inconsistencies (games that the user doesn't have in their library but they show multiple platforms)
ItemAction itemActions = await steamService.FindGameInconsistenciesWithUserAccount(platformGamesFromSteam, steamGames, steamActionLogRequest.UserId);
List<ItemAction> itemActions = await steamService.FindGameInconsistenciesWithUserAccount(platformGamesFromSteam, steamGames, steamActionLogRequest.UserId);

// step 4: Add games that don't have any problems to the user
await steamService.AddMissingGamesToUserGames(steamApiResponse, steamActionLogRequest.UserId);

// step 5: Find games user has but with different hours.
ItemAction itemActions2 = await steamService.FixTimeDifferences(steamApiResponse, platformGamesFromSteam, steamGames, steamActionLogRequest.UserId);
List<ItemAction> itemActions2 = await steamService.FixTimeDifferences(steamApiResponse, platformGamesFromSteam, steamGames, steamActionLogRequest.UserId);

// step 6: of synced games, auto add achievements user hasn't added to playlist yet (under development)
await steamAchievementService.AddMissingAchievementsToUser(steamActionLogRequest.UserId, steamActionLogRequest.UserSteamId);

itemActions.ItemOptions.AddRange(itemActions2.ItemOptions);
itemActions.AddRange(itemActions2);

return itemActions;
}
Expand Down
18 changes: 18 additions & 0 deletions PlaylistApp.Test/Services/SteamServiceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using PlaylistApp.Server.Services.SteamServices.SteamAchievementService.SteamAchievementService;
using PlaylistApp.Server.Services.SteamServices.SteamGameService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PlaylistApp.Test.Services;

public class SteamServiceTests
{
[Fact]
public void SteamAchievementServiceTest1()
{
ISteamAchievementService steamAchSvc;
}
}
3 changes: 1 addition & 2 deletions playlistapp.client/src/ApiServices/SteamService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const SteamService = {
console.error("No Steam Action Log Request provided.");
}
try {
const response = await axios.post<ItemAction>(
const response = await axios.post<ItemAction[]>(
`${import.meta.env.VITE_URL}/Steam/getuseractionlog`,
steamActionLogRequest,
{
Expand All @@ -19,7 +19,6 @@ export const SteamService = {
},
}
);
//console.log(Date.now().toString(), response.data.itemOptions);
return response.data;
} catch (error) {
console.error(
Expand Down
Loading