Audit léger: stats carrière, présence amis, AddGenericId #7
@@ -140,8 +140,18 @@ public class ClientController : Controller
|
||||
[HttpPost("AddGenericID")]
|
||||
[Produces(MediaTypeNames.Application.Json)]
|
||||
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
|
||||
public IActionResult AddGenericId(FAddGenericIDRequest request)
|
||||
public async Task<IActionResult> AddGenericId(FAddGenericIDRequest request)
|
||||
{
|
||||
// Persist the linked generic service id instead of dropping it (was a no-op stub).
|
||||
var userId = User.FindAuthUserId();
|
||||
if (request.GenericId != null && !string.IsNullOrEmpty(request.GenericId.ServiceName))
|
||||
{
|
||||
await _userDataService.UpdateAsync(userId, userId, new Dictionary<string, string>
|
||||
{
|
||||
["GenericId_" + request.GenericId.ServiceName] = request.GenericId.UserId ?? ""
|
||||
});
|
||||
}
|
||||
|
||||
return Ok(new ClientResponse<object>
|
||||
{
|
||||
Code = 200,
|
||||
|
||||
@@ -47,9 +47,28 @@ public class GetFriendList : ICloudScriptFunction<FYBaseSocialRequest, object?>
|
||||
if (steamIds.Count > 0)
|
||||
{
|
||||
var players = await _userService.FindManyAsync(PlayFabUserAuthType.Steam, steamIds);
|
||||
var nowUtc = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (player.Id == userId) continue; // never list yourself
|
||||
|
||||
// Presence persisted by UpdatePlayerPresenceState: online if seen in the last
|
||||
// 3 minutes. EYUserState best-effort: 0 = offline, 1 = online, 2 = in match.
|
||||
var onlineState = 0;
|
||||
var presenceData = await _userDataService.FindAsync(player.Id, player.Id, new List<string> { "PresenceState" });
|
||||
if (presenceData.TryGetValue("PresenceState", out var presenceRec) && !string.IsNullOrWhiteSpace(presenceRec.Value))
|
||||
{
|
||||
try
|
||||
{
|
||||
var presence = JsonSerializer.Deserialize<PlayerPresenceState>(presenceRec.Value);
|
||||
if (presence != null && nowUtc - presence.LastSeenUtc <= 180)
|
||||
{
|
||||
onlineState = presence.InMatch ? 2 : 1;
|
||||
}
|
||||
}
|
||||
catch { /* ignore malformed presence */ }
|
||||
}
|
||||
|
||||
friends.Add(new
|
||||
{
|
||||
profile = new
|
||||
@@ -58,7 +77,7 @@ public class GetFriendList : ICloudScriptFunction<FYBaseSocialRequest, object?>
|
||||
displayName = player.DisplayName,
|
||||
avatarUrl = "",
|
||||
},
|
||||
onlineState = 0, // EYUserState — real presence tracking is a later phase
|
||||
onlineState,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+11
-9
@@ -8,13 +8,8 @@ public class GetPlayerStatisticsRequestsClientRequest
|
||||
public string[] Statistics { get; set; }
|
||||
}
|
||||
|
||||
public class GetPlayerStatisticsRequestsClientResponse
|
||||
{
|
||||
// TODO: Unknown structure
|
||||
}
|
||||
|
||||
[CloudScriptFunction("GetPlayerStatisticsRequestsClient")]
|
||||
public class GetPlayerStatisticsRequestsClientFunction : ICloudScriptFunction<GetPlayerStatisticsRequestsClientRequest, GetPlayerStatisticsRequestsClientResponse>
|
||||
public class GetPlayerStatisticsRequestsClientFunction : ICloudScriptFunction<GetPlayerStatisticsRequestsClientRequest, object>
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
@@ -23,7 +18,7 @@ public class GetPlayerStatisticsRequestsClientFunction : ICloudScriptFunction<Ge
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
public async Task<GetPlayerStatisticsRequestsClientResponse> ExecuteAsync(GetPlayerStatisticsRequestsClientRequest request)
|
||||
public Task<object> ExecuteAsync(GetPlayerStatisticsRequestsClientRequest request)
|
||||
{
|
||||
var context = _httpContextAccessor.HttpContext;
|
||||
if (context == null)
|
||||
@@ -31,8 +26,15 @@ public class GetPlayerStatisticsRequestsClientFunction : ICloudScriptFunction<Ge
|
||||
throw new CloudScriptException("CloudScript was not called within a http request");
|
||||
}
|
||||
|
||||
return new GetPlayerStatisticsRequestsClientResponse
|
||||
// Return each requested statistic with a value so the career screen renders instead
|
||||
// of staying blank. Raid stats (kills/deaths/evacs/damage/…) come from the
|
||||
// client-hosted raid and aren't tracked server-side, so they report 0 for now.
|
||||
var stats = new List<object>();
|
||||
foreach (var name in request.Statistics ?? Array.Empty<string>())
|
||||
{
|
||||
};
|
||||
stats.Add(new { statisticName = name, value = 0 });
|
||||
}
|
||||
|
||||
return Task.FromResult<object>(new { statistics = stats });
|
||||
}
|
||||
}
|
||||
|
||||
+42
-3
@@ -1,12 +1,51 @@
|
||||
using Prospect.Server.Api.Services.CloudScript.Models;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Prospect.Server.Api.Services.Auth.Extensions;
|
||||
using Prospect.Server.Api.Services.CloudScript.Models;
|
||||
using Prospect.Server.Api.Services.UserData;
|
||||
|
||||
namespace Prospect.Server.Api.Services.CloudScript.Functions;
|
||||
|
||||
// Persisted presence, read back by GetFriendList to show friends' online / in-match state.
|
||||
public class PlayerPresenceState
|
||||
{
|
||||
[JsonPropertyName("inMatch")]
|
||||
public bool InMatch { get; set; }
|
||||
[JsonPropertyName("lastSeenUtc")]
|
||||
public long LastSeenUtc { get; set; }
|
||||
}
|
||||
|
||||
[CloudScriptFunction("UpdatePlayerPresenceState")]
|
||||
public class UpdatePlayerPresenceState : ICloudScriptFunction<FYUpdatePlayerPresenceStateRequest, object>
|
||||
{
|
||||
public Task<object> ExecuteAsync(FYUpdatePlayerPresenceStateRequest request)
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly UserDataService _userDataService;
|
||||
|
||||
public UpdatePlayerPresenceState(IHttpContextAccessor httpContextAccessor, UserDataService userDataService)
|
||||
{
|
||||
return Task.FromResult<object>(new { });
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_userDataService = userDataService;
|
||||
}
|
||||
|
||||
public async Task<object> ExecuteAsync(FYUpdatePlayerPresenceStateRequest request)
|
||||
{
|
||||
var context = _httpContextAccessor.HttpContext;
|
||||
if (context == null)
|
||||
{
|
||||
return new { };
|
||||
}
|
||||
|
||||
var userId = context.User.FindAuthUserId();
|
||||
var state = new PlayerPresenceState
|
||||
{
|
||||
InMatch = request.InMatch,
|
||||
LastSeenUtc = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
|
||||
};
|
||||
await _userDataService.UpdateAsync(
|
||||
userId, userId,
|
||||
new Dictionary<string, string> { ["PresenceState"] = JsonSerializer.Serialize(state) }
|
||||
);
|
||||
|
||||
return new { };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user