673 lines
25 KiB
C#
673 lines
25 KiB
C#
using GmRelay.Web.Services;
|
|
using GmRelay.Shared.Domain;
|
|
|
|
namespace GmRelay.Bot.Tests.Web;
|
|
|
|
public sealed class AuthorizedSessionServiceTests
|
|
{
|
|
[Fact]
|
|
public async Task GetUpcomingSessionsForGmAsync_ReturnsSessions_WhenGroupBelongsToGm()
|
|
{
|
|
var gmId = 1001L;
|
|
var groupId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", gmId)
|
|
],
|
|
sessions:
|
|
[
|
|
new(Guid.NewGuid(), groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", Guid.NewGuid(), 10, 42, 4, 1, 0)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
var sessions = await service.GetUpcomingSessionsForGmAsync(groupId, gmId);
|
|
|
|
Assert.NotNull(sessions);
|
|
Assert.Single(sessions);
|
|
Assert.Equal("Session A", sessions[0].Title);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetUpcomingSessionsForGmAsync_ReturnsSessions_WhenUserIsCoGm()
|
|
{
|
|
var ownerId = 1001L;
|
|
var coGmId = 2002L;
|
|
var groupId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", ownerId)
|
|
],
|
|
sessions:
|
|
[
|
|
new(Guid.NewGuid(), groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", Guid.NewGuid(), 10, 42, 4, 1, 0)
|
|
],
|
|
managers:
|
|
[
|
|
new(groupId, coGmId, GroupManagerRole.CoGm)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
var sessions = await service.GetUpcomingSessionsForGmAsync(groupId, coGmId);
|
|
|
|
Assert.NotNull(sessions);
|
|
Assert.Single(sessions);
|
|
Assert.Equal("Session A", sessions[0].Title);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetUpcomingSessionsForGmAsync_ReturnsNull_WhenGroupBelongsToAnotherGm()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", 2002L)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
var sessions = await service.GetUpcomingSessionsForGmAsync(groupId, 1001L);
|
|
|
|
Assert.Null(sessions);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetSessionForGmAsync_ReturnsSession_WhenSessionBelongsToOwnedGroup()
|
|
{
|
|
var gmId = 1001L;
|
|
var groupId = Guid.NewGuid();
|
|
var sessionId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", gmId)
|
|
],
|
|
sessions:
|
|
[
|
|
new(sessionId, groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", Guid.NewGuid(), 10, 42, 4, 1, 0)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
var session = await service.GetSessionForGmAsync(sessionId, gmId);
|
|
|
|
Assert.NotNull(session);
|
|
Assert.Equal(sessionId, session.Id);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetSessionForGmAsync_ReturnsNull_WhenSessionBelongsToAnotherGm()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var sessionId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", 2002L)
|
|
],
|
|
sessions:
|
|
[
|
|
new(sessionId, groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", Guid.NewGuid(), 10, 42, 4, 1, 0)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
var session = await service.GetSessionForGmAsync(sessionId, 1001L);
|
|
|
|
Assert.Null(session);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UpdateSessionForGmAsync_Throws_WhenSessionBelongsToAnotherGm()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var sessionId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", 2002L)
|
|
],
|
|
sessions:
|
|
[
|
|
new(sessionId, groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", Guid.NewGuid(), 10, 42, 4, 1, 0)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
var action = () => service.UpdateSessionForGmAsync(sessionId, 1001L, "Updated", DateTime.UtcNow.AddDays(1), "https://example.test/b", 5);
|
|
|
|
await Assert.ThrowsAsync<SessionAccessDeniedException>(action);
|
|
Assert.False(store.UpdateCalled);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UpdateSessionForGmAsync_UpdatesOwnedSession()
|
|
{
|
|
var gmId = 1001L;
|
|
var groupId = Guid.NewGuid();
|
|
var sessionId = Guid.NewGuid();
|
|
var scheduledAt = DateTime.UtcNow.AddDays(1);
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", gmId)
|
|
],
|
|
sessions:
|
|
[
|
|
new(sessionId, groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", Guid.NewGuid(), 10, 42, 4, 1, 0)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
await service.UpdateSessionForGmAsync(sessionId, gmId, "Updated", scheduledAt, "https://example.test/b", 5);
|
|
|
|
Assert.True(store.UpdateCalled);
|
|
Assert.Equal(groupId, store.LastUpdatedGroupId);
|
|
Assert.Equal(sessionId, store.LastUpdatedSessionId);
|
|
Assert.Equal("Updated", store.LastUpdatedTitle);
|
|
Assert.Equal(scheduledAt, store.LastUpdatedScheduledAt);
|
|
Assert.Equal("https://example.test/b", store.LastUpdatedJoinLink);
|
|
Assert.Equal(5, store.LastUpdatedMaxPlayers);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PromoteWaitlistedPlayerForGmAsync_PromotesOwnedSession()
|
|
{
|
|
var gmId = 1001L;
|
|
var groupId = Guid.NewGuid();
|
|
var sessionId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", gmId)
|
|
],
|
|
sessions:
|
|
[
|
|
new(sessionId, groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", Guid.NewGuid(), 10, 42, 4, 3, 1)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
await service.PromoteWaitlistedPlayerForGmAsync(sessionId, gmId);
|
|
|
|
Assert.True(store.PromoteCalled);
|
|
Assert.Equal(groupId, store.LastPromotedGroupId);
|
|
Assert.Equal(sessionId, store.LastPromotedSessionId);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UpdateBatchDetailsForGmAsync_Throws_WhenBatchBelongsToAnotherGm()
|
|
{
|
|
var batchId = Guid.NewGuid();
|
|
var groupId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", 2002L)
|
|
],
|
|
sessions:
|
|
[
|
|
new(Guid.NewGuid(), groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", batchId, 10, 42, 4, 1, 0)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
var action = () => service.UpdateBatchDetailsForGmAsync(batchId, 1001L, "Updated", "https://example.test/b");
|
|
|
|
await Assert.ThrowsAsync<SessionAccessDeniedException>(action);
|
|
Assert.False(store.UpdateBatchDetailsCalled);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UpdateBatchDetailsForGmAsync_UpdatesOwnedBatch()
|
|
{
|
|
var gmId = 1001L;
|
|
var groupId = Guid.NewGuid();
|
|
var batchId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", gmId)
|
|
],
|
|
sessions:
|
|
[
|
|
new(Guid.NewGuid(), groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", batchId, 10, 42, 4, 1, 0)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
await service.UpdateBatchDetailsForGmAsync(batchId, gmId, "Updated", "https://example.test/b");
|
|
|
|
Assert.True(store.UpdateBatchDetailsCalled);
|
|
Assert.Equal(batchId, store.LastUpdatedBatchId);
|
|
Assert.Equal(groupId, store.LastUpdatedBatchGroupId);
|
|
Assert.Equal("Updated", store.LastUpdatedBatchTitle);
|
|
Assert.Equal("https://example.test/b", store.LastUpdatedBatchJoinLink);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UpdateBatchDetailsForGmAsync_UpdatesBatch_WhenUserIsCoGm()
|
|
{
|
|
var ownerId = 1001L;
|
|
var coGmId = 2002L;
|
|
var groupId = Guid.NewGuid();
|
|
var batchId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", ownerId)
|
|
],
|
|
sessions:
|
|
[
|
|
new(Guid.NewGuid(), groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", batchId, 10, 42, 4, 1, 0)
|
|
],
|
|
managers:
|
|
[
|
|
new(groupId, coGmId, GroupManagerRole.CoGm)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
await service.UpdateBatchDetailsForGmAsync(batchId, coGmId, "Updated", "https://example.test/b");
|
|
|
|
Assert.True(store.UpdateBatchDetailsCalled);
|
|
Assert.Equal(batchId, store.LastUpdatedBatchId);
|
|
Assert.Equal(groupId, store.LastUpdatedBatchGroupId);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AddCoGmForOwnerAsync_AddsCoGm_WhenUserIsOwner()
|
|
{
|
|
var ownerId = 1001L;
|
|
var coGmId = 2002L;
|
|
var groupId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", ownerId)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
await service.AddCoGmForOwnerAsync(groupId, ownerId, coGmId, "Assistant GM", "assistant");
|
|
|
|
Assert.True(store.AddCoGmCalled);
|
|
Assert.Equal(groupId, store.LastAddedCoGmGroupId);
|
|
Assert.Equal(coGmId, store.LastAddedCoGmTelegramId);
|
|
Assert.Equal("Assistant GM", store.LastAddedCoGmDisplayName);
|
|
Assert.Equal("assistant", store.LastAddedCoGmUsername);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AddCoGmForOwnerAsync_Throws_WhenUserIsCoGm()
|
|
{
|
|
var ownerId = 1001L;
|
|
var coGmId = 2002L;
|
|
var newCoGmId = 3003L;
|
|
var groupId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", ownerId)
|
|
],
|
|
managers:
|
|
[
|
|
new(groupId, coGmId, GroupManagerRole.CoGm)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
var action = () => service.AddCoGmForOwnerAsync(groupId, coGmId, newCoGmId, "Second Assistant", null);
|
|
|
|
await Assert.ThrowsAsync<SessionAccessDeniedException>(action);
|
|
Assert.False(store.AddCoGmCalled);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RemoveCoGmForOwnerAsync_RemovesCoGm_WhenUserIsOwner()
|
|
{
|
|
var ownerId = 1001L;
|
|
var coGmId = 2002L;
|
|
var groupId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", ownerId)
|
|
],
|
|
managers:
|
|
[
|
|
new(groupId, coGmId, GroupManagerRole.CoGm)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
await service.RemoveCoGmForOwnerAsync(groupId, ownerId, coGmId);
|
|
|
|
Assert.True(store.RemoveCoGmCalled);
|
|
Assert.Equal(groupId, store.LastRemovedCoGmGroupId);
|
|
Assert.Equal(coGmId, store.LastRemovedCoGmTelegramId);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UpdateBatchNotificationModeForGmAsync_Throws_WhenBatchBelongsToAnotherGm()
|
|
{
|
|
var batchId = Guid.NewGuid();
|
|
var groupId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", 2002L)
|
|
],
|
|
sessions:
|
|
[
|
|
new(Guid.NewGuid(), groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", batchId, 10, 42, 4, 1, 0)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
var action = () => service.UpdateBatchNotificationModeForGmAsync(batchId, 1001L, SessionNotificationMode.GroupOnly);
|
|
|
|
await Assert.ThrowsAsync<SessionAccessDeniedException>(action);
|
|
Assert.False(store.UpdateBatchNotificationModeCalled);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UpdateBatchNotificationModeForGmAsync_UpdatesOwnedBatch()
|
|
{
|
|
var gmId = 1001L;
|
|
var groupId = Guid.NewGuid();
|
|
var batchId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", gmId)
|
|
],
|
|
sessions:
|
|
[
|
|
new(Guid.NewGuid(), groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", batchId, 10, 42, 4, 1, 0)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
await service.UpdateBatchNotificationModeForGmAsync(batchId, gmId, SessionNotificationMode.GroupOnly);
|
|
|
|
Assert.True(store.UpdateBatchNotificationModeCalled);
|
|
Assert.Equal(batchId, store.LastUpdatedNotificationBatchId);
|
|
Assert.Equal(groupId, store.LastUpdatedNotificationGroupId);
|
|
Assert.Equal(SessionNotificationMode.GroupOnly, store.LastUpdatedNotificationMode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RescheduleBatchForGmAsync_RejectsNonPositiveInterval()
|
|
{
|
|
var gmId = 1001L;
|
|
var groupId = Guid.NewGuid();
|
|
var batchId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", gmId)
|
|
],
|
|
sessions:
|
|
[
|
|
new(Guid.NewGuid(), groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", batchId, 10, 42, 4, 1, 0)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
var action = () => service.RescheduleBatchForGmAsync(batchId, gmId, DateTime.UtcNow.AddDays(7), intervalDays: 0);
|
|
|
|
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(action);
|
|
Assert.False(store.RescheduleBatchCalled);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RescheduleBatchForGmAsync_ReschedulesOwnedBatch()
|
|
{
|
|
var gmId = 1001L;
|
|
var groupId = Guid.NewGuid();
|
|
var batchId = Guid.NewGuid();
|
|
var firstScheduledAt = DateTime.UtcNow.AddDays(7);
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", gmId)
|
|
],
|
|
sessions:
|
|
[
|
|
new(Guid.NewGuid(), groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", batchId, 10, 42, 4, 1, 0)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
await service.RescheduleBatchForGmAsync(batchId, gmId, firstScheduledAt, intervalDays: 14);
|
|
|
|
Assert.True(store.RescheduleBatchCalled);
|
|
Assert.Equal(batchId, store.LastRescheduledBatchId);
|
|
Assert.Equal(groupId, store.LastRescheduledBatchGroupId);
|
|
Assert.Equal(firstScheduledAt, store.LastRescheduledFirstScheduledAt);
|
|
Assert.Equal(14, store.LastRescheduledIntervalDays);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CloneBatchForGmAsync_ClonesOwnedBatch()
|
|
{
|
|
var gmId = 1001L;
|
|
var groupId = Guid.NewGuid();
|
|
var batchId = Guid.NewGuid();
|
|
var store = new FakeSessionStore(
|
|
groups:
|
|
[
|
|
new(groupId, 42, "Alpha", gmId)
|
|
],
|
|
sessions:
|
|
[
|
|
new(Guid.NewGuid(), groupId, "Session A", DateTime.UtcNow, "Planned", "https://example.test/a", batchId, 10, 42, 4, 1, 0)
|
|
]);
|
|
var service = new AuthorizedSessionService(store);
|
|
|
|
await service.CloneBatchForGmAsync(batchId, gmId, BatchCloneInterval.NextWeek);
|
|
|
|
Assert.True(store.CloneBatchCalled);
|
|
Assert.Equal(batchId, store.LastClonedBatchId);
|
|
Assert.Equal(groupId, store.LastClonedBatchGroupId);
|
|
Assert.Equal(BatchCloneInterval.NextWeek, store.LastCloneInterval);
|
|
}
|
|
|
|
private sealed class FakeSessionStore(
|
|
IEnumerable<WebGameGroup>? groups = null,
|
|
IEnumerable<WebSession>? sessions = null,
|
|
IEnumerable<FakeGroupManager>? managers = null) : ISessionStore
|
|
{
|
|
private readonly Dictionary<Guid, WebGameGroup> groupsById = groups?.ToDictionary(group => group.Id) ?? [];
|
|
private readonly Dictionary<Guid, WebSession> sessionsById = sessions?.ToDictionary(session => session.Id) ?? [];
|
|
private readonly List<FakeGroupManager> managers = managers?.ToList() ?? [];
|
|
|
|
public bool UpdateCalled { get; private set; }
|
|
public bool PromoteCalled { get; private set; }
|
|
public bool UpdateBatchDetailsCalled { get; private set; }
|
|
public bool UpdateBatchNotificationModeCalled { get; private set; }
|
|
public bool RescheduleBatchCalled { get; private set; }
|
|
public bool CloneBatchCalled { get; private set; }
|
|
public bool AddCoGmCalled { get; private set; }
|
|
public bool RemoveCoGmCalled { get; private set; }
|
|
public Guid? LastUpdatedSessionId { get; private set; }
|
|
public Guid? LastUpdatedGroupId { get; private set; }
|
|
public string? LastUpdatedTitle { get; private set; }
|
|
public DateTime? LastUpdatedScheduledAt { get; private set; }
|
|
public string? LastUpdatedJoinLink { get; private set; }
|
|
public int? LastUpdatedMaxPlayers { get; private set; }
|
|
public Guid? LastPromotedSessionId { get; private set; }
|
|
public Guid? LastPromotedGroupId { get; private set; }
|
|
public Guid? LastUpdatedBatchId { get; private set; }
|
|
public Guid? LastUpdatedBatchGroupId { get; private set; }
|
|
public string? LastUpdatedBatchTitle { get; private set; }
|
|
public string? LastUpdatedBatchJoinLink { get; private set; }
|
|
public Guid? LastUpdatedNotificationBatchId { get; private set; }
|
|
public Guid? LastUpdatedNotificationGroupId { get; private set; }
|
|
public SessionNotificationMode? LastUpdatedNotificationMode { get; private set; }
|
|
public Guid? LastRescheduledBatchId { get; private set; }
|
|
public Guid? LastRescheduledBatchGroupId { get; private set; }
|
|
public DateTime? LastRescheduledFirstScheduledAt { get; private set; }
|
|
public int? LastRescheduledIntervalDays { get; private set; }
|
|
public Guid? LastClonedBatchId { get; private set; }
|
|
public Guid? LastClonedBatchGroupId { get; private set; }
|
|
public BatchCloneInterval? LastCloneInterval { get; private set; }
|
|
public Guid? LastAddedCoGmGroupId { get; private set; }
|
|
public long? LastAddedCoGmTelegramId { get; private set; }
|
|
public string? LastAddedCoGmDisplayName { get; private set; }
|
|
public string? LastAddedCoGmUsername { get; private set; }
|
|
public Guid? LastRemovedCoGmGroupId { get; private set; }
|
|
public long? LastRemovedCoGmTelegramId { get; private set; }
|
|
|
|
public Task<List<WebGameGroup>> GetGroupsForGmAsync(long gmId) =>
|
|
Task.FromResult(groupsById.Values.Where(group => IsManager(group.Id, gmId)).ToList());
|
|
|
|
public Task<WebGameGroup?> GetGroupAsync(Guid groupId)
|
|
{
|
|
groupsById.TryGetValue(groupId, out var group);
|
|
return Task.FromResult(group);
|
|
}
|
|
|
|
public Task<bool> IsGroupManagerAsync(Guid groupId, long telegramId) =>
|
|
Task.FromResult(IsManager(groupId, telegramId));
|
|
|
|
public Task<bool> IsGroupOwnerAsync(Guid groupId, long telegramId) =>
|
|
Task.FromResult(IsOwner(groupId, telegramId));
|
|
|
|
public Task<List<WebGroupManager>> GetGroupManagersAsync(Guid groupId)
|
|
{
|
|
if (!groupsById.TryGetValue(groupId, out var group))
|
|
{
|
|
return Task.FromResult(new List<WebGroupManager>());
|
|
}
|
|
|
|
var result = new List<WebGroupManager>
|
|
{
|
|
new(group.GmTelegramId, "Owner GM", null, GroupManagerRoleExtensions.OwnerValue, DateTime.UtcNow)
|
|
};
|
|
|
|
result.AddRange(managers
|
|
.Where(manager => manager.GroupId == groupId)
|
|
.Select(manager => new WebGroupManager(
|
|
manager.TelegramId,
|
|
$"Co-GM {manager.TelegramId}",
|
|
null,
|
|
manager.Role.ToDatabaseValue(),
|
|
DateTime.UtcNow)));
|
|
|
|
return Task.FromResult(result);
|
|
}
|
|
|
|
public Task<List<WebSession>> GetUpcomingSessionsAsync(Guid groupId) =>
|
|
Task.FromResult(sessionsById.Values.Where(session => session.GroupId == groupId).ToList());
|
|
|
|
public Task<WebSession?> GetSessionAsync(Guid sessionId)
|
|
{
|
|
sessionsById.TryGetValue(sessionId, out var session);
|
|
return Task.FromResult(session);
|
|
}
|
|
|
|
public Task<WebSessionBatch?> GetBatchAsync(Guid batchId)
|
|
{
|
|
var batchSessions = sessionsById.Values
|
|
.Where(session => session.BatchId == batchId)
|
|
.OrderBy(session => session.ScheduledAt)
|
|
.ToList();
|
|
|
|
if (batchSessions.Count == 0)
|
|
{
|
|
return Task.FromResult<WebSessionBatch?>(null);
|
|
}
|
|
|
|
var firstSession = batchSessions[0];
|
|
return Task.FromResult<WebSessionBatch?>(new(
|
|
batchId,
|
|
firstSession.GroupId,
|
|
firstSession.Title,
|
|
firstSession.JoinLink,
|
|
firstSession.ScheduledAt,
|
|
batchSessions[^1].ScheduledAt,
|
|
batchSessions.Count));
|
|
}
|
|
|
|
public Task UpdateSessionAsync(Guid sessionId, Guid groupId, string title, DateTime scheduledAt, string joinLink, int? maxPlayers)
|
|
{
|
|
UpdateCalled = true;
|
|
LastUpdatedSessionId = sessionId;
|
|
LastUpdatedGroupId = groupId;
|
|
LastUpdatedTitle = title;
|
|
LastUpdatedScheduledAt = scheduledAt;
|
|
LastUpdatedJoinLink = joinLink;
|
|
LastUpdatedMaxPlayers = maxPlayers;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task PromoteWaitlistedPlayerAsync(Guid sessionId, Guid groupId)
|
|
{
|
|
PromoteCalled = true;
|
|
LastPromotedSessionId = sessionId;
|
|
LastPromotedGroupId = groupId;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task UpdateBatchDetailsAsync(Guid batchId, Guid groupId, string title, string joinLink)
|
|
{
|
|
UpdateBatchDetailsCalled = true;
|
|
LastUpdatedBatchId = batchId;
|
|
LastUpdatedBatchGroupId = groupId;
|
|
LastUpdatedBatchTitle = title;
|
|
LastUpdatedBatchJoinLink = joinLink;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task UpdateBatchNotificationModeAsync(Guid batchId, Guid groupId, SessionNotificationMode notificationMode)
|
|
{
|
|
UpdateBatchNotificationModeCalled = true;
|
|
LastUpdatedNotificationBatchId = batchId;
|
|
LastUpdatedNotificationGroupId = groupId;
|
|
LastUpdatedNotificationMode = notificationMode;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task RescheduleBatchAsync(Guid batchId, Guid groupId, DateTime firstScheduledAt, int intervalDays)
|
|
{
|
|
RescheduleBatchCalled = true;
|
|
LastRescheduledBatchId = batchId;
|
|
LastRescheduledBatchGroupId = groupId;
|
|
LastRescheduledFirstScheduledAt = firstScheduledAt;
|
|
LastRescheduledIntervalDays = intervalDays;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task<WebSessionBatch> CloneBatchAsync(Guid batchId, Guid groupId, BatchCloneInterval interval)
|
|
{
|
|
CloneBatchCalled = true;
|
|
LastClonedBatchId = batchId;
|
|
LastClonedBatchGroupId = groupId;
|
|
LastCloneInterval = interval;
|
|
return Task.FromResult(new WebSessionBatch(
|
|
Guid.NewGuid(),
|
|
groupId,
|
|
"Session A",
|
|
"https://example.test/a",
|
|
DateTime.UtcNow.AddDays(7),
|
|
DateTime.UtcNow.AddDays(7),
|
|
1));
|
|
}
|
|
|
|
public Task AddGroupCoGmAsync(Guid groupId, long ownerTelegramId, long coGmTelegramId, string displayName, string? telegramUsername)
|
|
{
|
|
AddCoGmCalled = true;
|
|
LastAddedCoGmGroupId = groupId;
|
|
LastAddedCoGmTelegramId = coGmTelegramId;
|
|
LastAddedCoGmDisplayName = displayName;
|
|
LastAddedCoGmUsername = telegramUsername;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task RemoveGroupCoGmAsync(Guid groupId, long coGmTelegramId)
|
|
{
|
|
RemoveCoGmCalled = true;
|
|
LastRemovedCoGmGroupId = groupId;
|
|
LastRemovedCoGmTelegramId = coGmTelegramId;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private bool IsManager(Guid groupId, long telegramId) =>
|
|
IsOwner(groupId, telegramId) ||
|
|
managers.Any(manager => manager.GroupId == groupId && manager.TelegramId == telegramId);
|
|
|
|
private bool IsOwner(Guid groupId, long telegramId) =>
|
|
groupsById.TryGetValue(groupId, out var group) && group.GmTelegramId == telegramId;
|
|
}
|
|
|
|
private sealed record FakeGroupManager(Guid GroupId, long TelegramId, GroupManagerRole Role);
|
|
}
|