clean up structs and seperate zone definitions

This commit is contained in:
azyges
2025-11-05 01:40:48 +09:00
parent 96627e3b85
commit 7cfe29e511
5 changed files with 126 additions and 112 deletions

View File

@@ -5,6 +5,7 @@ using System.Text.Json;
using LightlessSync.API.Data.Enum;
using LightlessSync.API.Dto.Chat;
using LightlessSync.API.Dto.User;
using LightlessSyncServer.Models;
using LightlessSyncServer.Services;
using LightlessSyncServer.Utils;
using LightlessSyncShared.Models;
@@ -318,8 +319,8 @@ public partial class LightlessHub
return;
}
var requestedChannelKey = ChatChannelService.ChannelKey.FromDescriptor(channel);
var messageChannelKey = ChatChannelService.ChannelKey.FromDescriptor(messageEntry.Channel.WithNormalizedCustomKey());
var requestedChannelKey = ChannelKey.FromDescriptor(channel);
var messageChannelKey = ChannelKey.FromDescriptor(messageEntry.Channel.WithNormalizedCustomKey());
if (!requestedChannelKey.Equals(messageChannelKey))
{
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Error, "The reported message no longer matches this channel.").ConfigureAwait(false);
@@ -433,7 +434,7 @@ public partial class LightlessHub
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Information, "Thank you. Your report has been queued for moderator review.").ConfigureAwait(false);
}
private ChatSenderDescriptor BuildSenderDescriptor(ChatChannelDescriptor descriptor, ChatChannelService.ChatParticipantInfo participant, bool includeSensitiveInfo = false)
private ChatSenderDescriptor BuildSenderDescriptor(ChatChannelDescriptor descriptor, ChatParticipantInfo participant, bool includeSensitiveInfo = false)
{
var kind = descriptor.Type == ChatChannelType.Group
? ChatSenderKind.IdentifiedUser
@@ -566,13 +567,4 @@ public partial class LightlessHub
await Clients.Client(connectionId).Client_ReceiveServerMessage(MessageSeverity.Error, "Your chat access has been revoked.").ConfigureAwait(false);
}
}
private readonly record struct ChatReportSnapshotItem(
string MessageId,
DateTime SentAtUtc,
string SenderUserUid,
string? SenderAlias,
bool SenderIsLightfinder,
string? SenderHashedCid,
string Message);
}
}

View File

@@ -9,4 +9,4 @@ public class BroadcastRedisEntry()
public bool OwnedBy(string userUid) => !string.IsNullOrEmpty(userUid) && string.Equals(OwnerUID, userUid, StringComparison.Ordinal);
public bool HasOwner() => !string.IsNullOrEmpty(OwnerUID);
}
}

View File

@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using LightlessSync.API.Data;
using LightlessSync.API.Dto.Chat;
namespace LightlessSyncServer.Models;
internal readonly record struct ChatReportSnapshotItem(
string MessageId,
DateTime SentAtUtc,
string SenderUserUid,
string? SenderAlias,
bool SenderIsLightfinder,
string? SenderHashedCid,
string Message);
public readonly record struct ChatPresenceEntry(
ChatChannelDescriptor Channel,
ChannelKey ChannelKey,
string DisplayName,
ChatParticipantInfo Participant,
DateTime UpdatedAt);
public readonly record struct ChatParticipantInfo(
string Token,
string UserUid,
UserData? User,
string? HashedCid,
bool IsLightfinder);
public readonly record struct ChatMessageLogEntry(
string MessageId,
ChatChannelDescriptor Channel,
DateTime SentAtUtc,
string SenderToken,
string SenderUserUid,
UserData? SenderUser,
bool SenderIsLightfinder,
string? SenderHashedCid,
string Message);
public readonly record struct ZoneChannelDefinition(
string Key,
string DisplayName,
ChatChannelDescriptor Descriptor,
IReadOnlyList<string> TerritoryNames);
public readonly record struct ChannelKey(ChatChannelType Type, ushort WorldId, string CustomKey)
{
public static ChannelKey FromDescriptor(ChatChannelDescriptor descriptor) =>
new(
descriptor.Type,
descriptor.Type == ChatChannelType.Zone ? descriptor.WorldId : (ushort)0,
NormalizeKey(descriptor.CustomKey));
private static string NormalizeKey(string? value) =>
string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim().ToUpperInvariant();
}

View File

@@ -0,0 +1,57 @@
using System.Collections.Generic;
using LightlessSync.API.Dto.Chat;
namespace LightlessSyncServer.Models;
internal static class ChatZoneDefinitions
{
public static IReadOnlyList<ZoneChannelDefinition> Defaults { get; } =
new[]
{
new ZoneChannelDefinition(
Key: "limsa",
DisplayName: "Limsa Lominsa",
Descriptor: new ChatChannelDescriptor
{
Type = ChatChannelType.Zone,
WorldId = 0,
ZoneId = 0,
CustomKey = "limsa"
},
TerritoryNames: new[]
{
"Limsa Lominsa Lower Decks",
"Limsa Lominsa Upper Decks"
}),
new ZoneChannelDefinition(
Key: "gridania",
DisplayName: "Gridania",
Descriptor: new ChatChannelDescriptor
{
Type = ChatChannelType.Zone,
WorldId = 0,
ZoneId = 0,
CustomKey = "gridania"
},
TerritoryNames: new[]
{
"New Gridania",
"Old Gridania"
}),
new ZoneChannelDefinition(
Key: "uldah",
DisplayName: "Ul'dah",
Descriptor: new ChatChannelDescriptor
{
Type = ChatChannelType.Zone,
WorldId = 0,
ZoneId = 0,
CustomKey = "uldah"
},
TerritoryNames: new[]
{
"Ul'dah - Steps of Nald",
"Ul'dah - Steps of Thal"
})
};
}

View File

@@ -1,9 +1,10 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using LightlessSync.API.Data;
using LightlessSync.API.Dto.Chat;
using LightlessSyncServer.Models;
using Microsoft.Extensions.Logging;
namespace LightlessSyncServer.Services;
@@ -11,7 +12,7 @@ namespace LightlessSyncServer.Services;
public sealed class ChatChannelService
{
private readonly ILogger<ChatChannelService> _logger;
private readonly Dictionary<string, ZoneChannelDefinition> _zoneDefinitions = new(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, ZoneChannelDefinition> _zoneDefinitions;
private readonly Dictionary<ChannelKey, HashSet<string>> _membersByChannel = new();
private readonly Dictionary<string, Dictionary<ChannelKey, ChatPresenceEntry>> _presenceByUser = new(StringComparer.Ordinal);
private readonly Dictionary<ChannelKey, Dictionary<string, ChatParticipantInfo>> _participantsByChannel = new();
@@ -23,54 +24,8 @@ public sealed class ChatChannelService
public ChatChannelService(ILogger<ChatChannelService> logger)
{
_logger = logger;
AddZoneDefinition(new ZoneChannelDefinition(
Key: "limsa",
DisplayName: "Limsa Lominsa",
Descriptor: new ChatChannelDescriptor
{
Type = ChatChannelType.Zone,
WorldId = 0,
ZoneId = 0,
CustomKey = "limsa"
},
TerritoryNames: new[]
{
"Limsa Lominsa Lower Decks",
"Limsa Lominsa Upper Decks"
}));
AddZoneDefinition(new ZoneChannelDefinition(
Key: "gridania",
DisplayName: "Gridania",
Descriptor: new ChatChannelDescriptor
{
Type = ChatChannelType.Zone,
WorldId = 0,
ZoneId = 0,
CustomKey = "gridania"
},
TerritoryNames: new[]
{
"New Gridania",
"Old Gridania"
}));
AddZoneDefinition(new ZoneChannelDefinition(
Key: "uldah",
DisplayName: "Ul'dah",
Descriptor: new ChatChannelDescriptor
{
Type = ChatChannelType.Zone,
WorldId = 0,
ZoneId = 0,
CustomKey = "uldah"
},
TerritoryNames: new[]
{
"Ul'dah - Steps of Nald",
"Ul'dah - Steps of Thal"
}));
_zoneDefinitions = ChatZoneDefinitions.Defaults
.ToDictionary(definition => definition.Key, StringComparer.OrdinalIgnoreCase);
}
public IReadOnlyList<ZoneChatChannelInfoDto> GetZoneChannelInfos() =>
@@ -454,11 +409,6 @@ public sealed class ChatChannelService
return true;
}
private void AddZoneDefinition(ZoneChannelDefinition definition)
{
_zoneDefinitions[definition.Key] = definition;
}
private static string GenerateToken()
{
Span<byte> buffer = stackalloc byte[8];
@@ -468,47 +418,4 @@ public sealed class ChatChannelService
private static string Describe(ChannelKey key)
=> $"{key.Type}:{key.WorldId}:{key.CustomKey}";
private static string NormalizeKey(string? value)
=> string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim().ToUpperInvariant();
public readonly record struct ChatPresenceEntry(
ChatChannelDescriptor Channel,
ChannelKey ChannelKey,
string DisplayName,
ChatParticipantInfo Participant,
DateTime UpdatedAt);
public readonly record struct ChatParticipantInfo(
string Token,
string UserUid,
UserData? User,
string? HashedCid,
bool IsLightfinder);
public readonly record struct ChatMessageLogEntry(
string MessageId,
ChatChannelDescriptor Channel,
DateTime SentAtUtc,
string SenderToken,
string SenderUserUid,
UserData? SenderUser,
bool SenderIsLightfinder,
string? SenderHashedCid,
string Message);
public readonly record struct ZoneChannelDefinition(
string Key,
string DisplayName,
ChatChannelDescriptor Descriptor,
IReadOnlyList<string> TerritoryNames);
public readonly record struct ChannelKey(ChatChannelType Type, ushort WorldId, string CustomKey)
{
public static ChannelKey FromDescriptor(ChatChannelDescriptor descriptor)
=> new(
descriptor.Type,
descriptor.Type == ChatChannelType.Zone ? descriptor.WorldId : (ushort)0,
NormalizeKey(descriptor.CustomKey));
}
}