69 lines
2.5 KiB
C#
69 lines
2.5 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.SignalR;
|
|
using PlotLine.Models;
|
|
using PlotLine.Services;
|
|
using System.Security.Claims;
|
|
|
|
namespace PlotLine.Hubs;
|
|
|
|
[Authorize]
|
|
public sealed class WordCompanionFollowHub(IWordCompanionPresenceService presence) : Hub
|
|
{
|
|
public override async Task OnConnectedAsync()
|
|
{
|
|
if (TryGetUserId(out var userId))
|
|
{
|
|
await Groups.AddToGroupAsync(Context.ConnectionId, PresenceGroup(userId));
|
|
}
|
|
|
|
await base.OnConnectedAsync();
|
|
}
|
|
|
|
public async Task<WordCompanionPresenceStatus> WatchCompanionPresence()
|
|
{
|
|
var userId = RequireUserId();
|
|
await Groups.AddToGroupAsync(Context.ConnectionId, PresenceGroup(userId));
|
|
return await presence.GetStatusAsync(userId);
|
|
}
|
|
|
|
public async Task<WordCompanionPresenceStatus> RegisterCompanion(WordCompanionPresenceRegistration registration)
|
|
{
|
|
var userId = RequireUserId();
|
|
if (registration.UserID.HasValue && registration.UserID.Value != userId)
|
|
{
|
|
throw new HubException("The Companion is signed in as a different user.");
|
|
}
|
|
|
|
var status = await presence.RegisterAsync(userId, Context.ConnectionId, registration);
|
|
await Clients.Group(PresenceGroup(userId)).SendAsync("WordCompanionPresenceChanged", status);
|
|
return status;
|
|
}
|
|
|
|
public async Task<WordCompanionPresenceStatus> CompanionHeartbeat(WordCompanionPresenceHeartbeat heartbeat)
|
|
{
|
|
var userId = RequireUserId();
|
|
var status = await presence.HeartbeatAsync(userId, Context.ConnectionId, heartbeat);
|
|
await Clients.Group(PresenceGroup(userId)).SendAsync("WordCompanionPresenceChanged", status);
|
|
return status;
|
|
}
|
|
|
|
public override async Task OnDisconnectedAsync(Exception? exception)
|
|
{
|
|
var status = await presence.DisconnectAsync(Context.ConnectionId);
|
|
if (status is not null)
|
|
{
|
|
await Clients.Group(PresenceGroup(status.UserID)).SendAsync("WordCompanionPresenceChanged", status);
|
|
}
|
|
|
|
await base.OnDisconnectedAsync(exception);
|
|
}
|
|
|
|
private int RequireUserId()
|
|
=> TryGetUserId(out var userId) ? userId : throw new HubException("Sign in to use the Word Companion.");
|
|
|
|
private bool TryGetUserId(out int userId)
|
|
=> int.TryParse(Context.User?.FindFirstValue(ClaimTypes.NameIdentifier), out userId);
|
|
|
|
private static string PresenceGroup(int userId) => $"word-companion-presence:{userId}";
|
|
}
|