diff --git a/LightlessSyncServer/LightlessSyncAuthService/LightlessSyncAuthService.csproj b/LightlessSyncServer/LightlessSyncAuthService/LightlessSyncAuthService.csproj index 76899a7..68736b6 100644 --- a/LightlessSyncServer/LightlessSyncAuthService/LightlessSyncAuthService.csproj +++ b/LightlessSyncServer/LightlessSyncAuthService/LightlessSyncAuthService.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable diff --git a/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.Functions.cs b/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.Functions.cs index b0910f4..a329f8e 100644 --- a/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.Functions.cs +++ b/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.Functions.cs @@ -152,7 +152,7 @@ public partial class LightlessHub BroadcastRedisEntry? entry; try { - entry = JsonSerializer.Deserialize(broadcastValue!); + entry = JsonSerializer.Deserialize(broadcastValue.ToString()!); } catch (Exception ex) { diff --git a/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.User.cs b/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.User.cs index d41211a..6120b20 100644 --- a/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.User.cs +++ b/LightlessSyncServer/LightlessSyncServer/Hubs/LightlessHub.User.cs @@ -336,7 +336,7 @@ public partial class LightlessHub BroadcastRedisEntry? entry; try { - entry = JsonSerializer.Deserialize(broadcastValue.Value!); + entry = JsonSerializer.Deserialize(broadcastValue.Value.ToString()!); } catch (Exception ex) { @@ -438,7 +438,7 @@ public partial class LightlessHub { try { - existingEntry = JsonSerializer.Deserialize(existingValue!); + existingEntry = JsonSerializer.Deserialize(existingValue.ToString()!); } catch (Exception ex) { @@ -477,7 +477,7 @@ public partial class LightlessHub BroadcastRedisEntry? entry; try { - entry = JsonSerializer.Deserialize(value!); + entry = JsonSerializer.Deserialize(value.ToString()!); } catch (Exception ex) { @@ -536,7 +536,7 @@ public partial class LightlessHub BroadcastRedisEntry? entry; try { - entry = JsonSerializer.Deserialize(value.Value!); + entry = JsonSerializer.Deserialize(value.Value.ToString()!); } catch (Exception ex) { @@ -590,7 +590,7 @@ public partial class LightlessHub BroadcastRedisEntry? entry; try { - entry = JsonSerializer.Deserialize(result.Value!); + entry = JsonSerializer.Deserialize(result.Value.ToString()!); } catch { @@ -645,7 +645,7 @@ public partial class LightlessHub BroadcastRedisEntry? entry; try { - entry = JsonSerializer.Deserialize(value!); + entry = JsonSerializer.Deserialize(value.ToString()!); } catch { @@ -728,7 +728,7 @@ public partial class LightlessHub try { - entry = JsonSerializer.Deserialize(raw!); + entry = JsonSerializer.Deserialize(raw.ToString()!); if (entry is not null && !string.Equals(entry.HashedCID, cid, StringComparison.Ordinal)) { _logger.LogCallWarning(LightlessHubLogger.Args("mismatched broadcast cid in batch", "Requested", cid, "EntryCID", entry.HashedCID)); diff --git a/LightlessSyncServer/LightlessSyncServer/LightlessSyncServer.csproj b/LightlessSyncServer/LightlessSyncServer/LightlessSyncServer.csproj index 2891a14..f670319 100644 --- a/LightlessSyncServer/LightlessSyncServer/LightlessSyncServer.csproj +++ b/LightlessSyncServer/LightlessSyncServer/LightlessSyncServer.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 aspnet-LightlessSyncServer-BA82A12A-0B30-463C-801D-B7E81318CD50 1.1.0.0 enable diff --git a/LightlessSyncServer/LightlessSyncServices/Discord/DiscordBot.cs b/LightlessSyncServer/LightlessSyncServices/Discord/DiscordBot.cs index 87fc36f..63bee79 100644 --- a/LightlessSyncServer/LightlessSyncServices/Discord/DiscordBot.cs +++ b/LightlessSyncServer/LightlessSyncServices/Discord/DiscordBot.cs @@ -1,9 +1,6 @@ -using System.Collections.Generic; -using System; using System.Globalization; using System.Text; using System.Text.Json; -using System.Linq; using Discord; using Discord.Interactions; using Discord.Rest; @@ -872,16 +869,17 @@ internal class DiscordBot : IHostedService string? SenderHashedCid, string Message); - private async Task UpdateStatusAsync(CancellationToken token) + private async Task UpdateStatusAsync(CancellationToken cancellationToken) { - while (!token.IsCancellationRequested) + while (!cancellationToken.IsCancellationRequested) { var endPoint = _connectionMultiplexer.GetEndPoints().First(); - var onlineUsers = await _connectionMultiplexer.GetServer(endPoint).KeysAsync(pattern: "UID:*").CountAsync().ConfigureAwait(false); + var keys = _connectionMultiplexer.GetServer(endPoint).KeysAsync(pattern: "UID:*"); + var onlineUsers = await keys.CountAsync(cancellationToken).ConfigureAwait(false); - _logger.LogInformation("Users online: " + onlineUsers); + _logger.LogInformation("Users online: " + onlineUsers); await _discordClient.SetActivityAsync(new Game("Lightless for " + onlineUsers + " Users")).ConfigureAwait(false); - await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false); + await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken).ConfigureAwait(false); } } } diff --git a/LightlessSyncServer/LightlessSyncServices/Discord/LightlessModule.cs b/LightlessSyncServer/LightlessSyncServices/Discord/LightlessModule.cs index 5d531a9..766281e 100644 --- a/LightlessSyncServer/LightlessSyncServices/Discord/LightlessModule.cs +++ b/LightlessSyncServer/LightlessSyncServices/Discord/LightlessModule.cs @@ -43,33 +43,54 @@ public class LightlessModule : InteractionModuleBase try { - EmbedBuilder eb = new(); - using var scope = _services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); await using (db.ConfigureAwait(false)) { - eb = await HandleUserInfo(eb, db, Context.User.Id, secondaryUid, discordUser?.Id ?? null, uid); + var (mainEmbed, profileEmbed) = await HandleUserInfo(db, Context.User.Id, secondaryUid, discordUser?.Id ?? null, uid); string uidToGet = await GetUserUID(db, secondaryUid, discordUser?.Id ?? null, uid).ConfigureAwait(false); var profileData = await GetUserProfileData(db, uidToGet).ConfigureAwait(false); + + List embeds = new() { mainEmbed }; + if (profileEmbed != null) + { + embeds.Add(profileEmbed); + } + if (profileData != null) { byte[] profileImage = GetProfileImage(profileData); byte[] bannerImage = GetBannerImage(profileData); using MemoryStream profileImgStream = new(profileImage); using MemoryStream bannerImgStream = new(bannerImage); - eb.WithThumbnailUrl("attachment://profileimage.png"); - eb.WithImageUrl("attachment://bannerimage.png"); + + var mainEmbedData = embeds[0]; + var mainEmbedBuilder = new EmbedBuilder() + .WithTitle(mainEmbedData.Title) + .WithDescription(mainEmbedData.Description) + .WithThumbnailUrl("attachment://profileimage.png") + .WithImageUrl("attachment://bannerimage.png"); + + if (mainEmbedData.Fields != null) + { + foreach (var field in mainEmbedData.Fields) + { + mainEmbedBuilder.AddField(field.Name, field.Value, field.Inline); + } + } + + embeds[0] = mainEmbedBuilder.Build(); + await RespondWithFilesAsync( new[] { new FileAttachment(profileImgStream, "profileimage.png"), new FileAttachment(bannerImgStream, "bannerimage.png") }, - embeds: new[] { eb.Build() }, + embeds: embeds.ToArray(), ephemeral: true).ConfigureAwait(false); } else { await RespondAsync( - embeds: new[] { eb.Build() }, + embeds: embeds.ToArray(), ephemeral: true).ConfigureAwait(false); } } @@ -449,7 +470,7 @@ public class LightlessModule : InteractionModuleBase return embed.Build(); } - private async Task HandleUserInfo(EmbedBuilder eb, LightlessDbContext db, ulong id, string? secondaryUserUid = null, ulong? optionalUser = null, string? uid = null) + private async Task<(Embed mainEmbed, Embed? profileEmbed)> HandleUserInfo(LightlessDbContext db, ulong id, string? secondaryUserUid = null, ulong? optionalUser = null, string? uid = null) { bool showForSecondaryUser = secondaryUserUid != null; @@ -459,18 +480,20 @@ public class LightlessModule : InteractionModuleBase if (primaryUser == null) { + EmbedBuilder eb = new(); eb.WithTitle("No account"); eb.WithDescription("No Lightless account was found associated to your Discord user"); - return eb; + return (eb.Build(), null); } bool isAdminCall = primaryUser.User.IsModerator || primaryUser.User.IsAdmin; if ((optionalUser != null || uid != null) && !isAdminCall) { + EmbedBuilder eb = new(); eb.WithTitle("Unauthorized"); eb.WithDescription("You are not authorized to view another users' information"); - return eb; + return (eb.Build(), null); } else if ((optionalUser != null || uid != null) && isAdminCall) { @@ -486,9 +509,10 @@ public class LightlessModule : InteractionModuleBase if (userInDb == null) { + EmbedBuilder eb = new(); eb.WithTitle("No account"); eb.WithDescription("The Discord user has no valid Lightless account"); - return eb; + return (eb.Build(), null); } userToCheckForDiscordId = userInDb.DiscordId; @@ -501,9 +525,10 @@ public class LightlessModule : InteractionModuleBase dbUser = (await db.Auth.Include(u => u.User).SingleOrDefaultAsync(u => u.PrimaryUserUID == dbUser.UID && u.UserUID == secondaryUserUid))?.User; if (dbUser == null) { + EmbedBuilder eb = new(); eb.WithTitle("No such secondary UID"); eb.WithDescription($"A secondary UID {secondaryUserUid} was not found attached to your primary UID {primaryUser.User.UID}."); - return eb; + return (eb.Build(), null); } } @@ -513,55 +538,61 @@ public class LightlessModule : InteractionModuleBase var profile = await db.UserProfileData.Where(u => u.UserUID == dbUser.UID).SingleOrDefaultAsync().ConfigureAwait(false); var identity = await _connectionMultiplexer.GetDatabase().StringGetAsync("UID:" + dbUser.UID).ConfigureAwait(false); - eb.WithTitle("User Information"); - eb.WithDescription("This is the user information for Discord User <@" + userToCheckForDiscordId + ">" + Environment.NewLine + Environment.NewLine + EmbedBuilder mainEmbed = new(); + mainEmbed.WithTitle("User Information"); + mainEmbed.WithDescription("This is the user information for Discord User <@" + userToCheckForDiscordId + ">" + Environment.NewLine + Environment.NewLine + "If you want to verify your secret key is valid, go to https://emn178.github.io/online-tools/sha256.html and copy your secret key into there and compare it to the Hashed Secret Key provided below."); - eb.AddField("UID", dbUser.UID); + mainEmbed.AddField("UID", dbUser.UID); if (!string.IsNullOrEmpty(dbUser.Alias)) { - eb.AddField("Vanity UID", dbUser.Alias); + mainEmbed.AddField("Vanity UID", dbUser.Alias); } if (showForSecondaryUser) { - eb.AddField("Primary UID for " + dbUser.UID, auth.PrimaryUserUID); + mainEmbed.AddField("Primary UID for " + dbUser.UID, auth.PrimaryUserUID); } else { var secondaryUIDs = await db.Auth.Where(p => p.PrimaryUserUID == dbUser.UID).Select(p => p.UserUID).ToListAsync(); if (secondaryUIDs.Any()) { - eb.AddField("Secondary UIDs", string.Join(Environment.NewLine, secondaryUIDs)); + mainEmbed.AddField("Secondary UIDs", string.Join(Environment.NewLine, secondaryUIDs)); } } - if(profile != null) - { - eb.AddField("Profile Description", string.IsNullOrEmpty(profile.UserDescription) ? "(No description set)" : profile.UserDescription); - eb.AddField("Profile NSFW", profile.IsNSFW); - eb.AddField("Profile Disabled", profile.ProfileDisabled); - eb.AddField("Profile Flagged for Report", profile.FlaggedForReport); - eb.AddField("Profile Tags", profile.Tags != null && profile.Tags.Length > 0 ? string.Join(", ", profile.Tags) : "(No tags set)"); - } - eb.AddField("Last Online (UTC)", dbUser.LastLoggedIn.ToString("U")); - eb.AddField("Currently online ", !string.IsNullOrEmpty(identity)); - eb.AddField("Hashed Secret Key", auth.HashedKey); - eb.AddField("Joined Syncshells", groupsJoined.Count); - eb.AddField("Owned Syncshells", groups.Count); + mainEmbed.AddField("Last Online (UTC)", dbUser.LastLoggedIn.ToString("U")); + mainEmbed.AddField("Currently online ", !string.IsNullOrEmpty(identity)); + mainEmbed.AddField("Hashed Secret Key", auth.HashedKey); + mainEmbed.AddField("Joined Syncshells", groupsJoined.Count); + mainEmbed.AddField("Owned Syncshells", groups.Count); foreach (var group in groups) { var syncShellUserCount = await db.GroupPairs.CountAsync(g => g.GroupGID == group.GID).ConfigureAwait(false); if (!string.IsNullOrEmpty(group.Alias)) { - eb.AddField("Owned Syncshell " + group.GID + " Vanity ID", group.Alias); + mainEmbed.AddField("Owned Syncshell " + group.GID + " Vanity ID", group.Alias); } - eb.AddField("Owned Syncshell " + group.GID + " User Count", syncShellUserCount); + mainEmbed.AddField("Owned Syncshell " + group.GID + " User Count", syncShellUserCount); } if (isAdminCall && !string.IsNullOrEmpty(identity)) { - eb.AddField("Character Ident", identity); + mainEmbed.AddField("Character Ident", identity); } - return eb; + Embed? profileEmbedResult = null; + if (profile != null) + { + EmbedBuilder profileEmbedBuilder = new(); + profileEmbedBuilder.WithTitle("User Profile"); + profileEmbedBuilder.WithDescription("Profile Description: " + (string.IsNullOrEmpty(profile.UserDescription) ? "(No description set)" : profile.UserDescription)); + profileEmbedBuilder.AddField("Profile NSFW", profile.IsNSFW); + profileEmbedBuilder.AddField("Profile Disabled", profile.ProfileDisabled); + profileEmbedBuilder.AddField("Profile Flagged for Report", profile.FlaggedForReport); + profileEmbedBuilder.AddField("Profile Tags", profile.Tags != null && profile.Tags.Length > 0 ? string.Join(", ", profile.Tags) : "(No tags set)"); + profileEmbedResult = profileEmbedBuilder.Build(); + } + + return (mainEmbed.Build(), profileEmbedResult); } private async Task GetUserUID(LightlessDbContext db, string? secondaryUserUid = null, ulong? optionalUser = null, string? uid = null) @@ -578,7 +609,7 @@ public class LightlessModule : InteractionModuleBase } else if (uid != null) { - userInDb = await db.LodeStoneAuth.Include(u => u.User).SingleOrDefaultAsync(u => u.User.UID == uid || u.User.Alias == uid).ConfigureAwait(false); + userInDb = await db.LodeStoneAuth.Include(u => u.User).SingleOrDefaultAsync(u => u.User.UID == uid || u.User.Alias == uid). ConfigureAwait(false); } if (userInDb == null) { diff --git a/LightlessSyncServer/LightlessSyncServices/LightlessSyncServices.csproj b/LightlessSyncServer/LightlessSyncServices/LightlessSyncServices.csproj index 3a2057e..c2b33ef 100644 --- a/LightlessSyncServer/LightlessSyncServices/LightlessSyncServices.csproj +++ b/LightlessSyncServer/LightlessSyncServices/LightlessSyncServices.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable @@ -21,7 +21,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -32,6 +32,7 @@ + diff --git a/LightlessSyncServer/LightlessSyncShared/LightlessSyncShared.csproj b/LightlessSyncServer/LightlessSyncShared/LightlessSyncShared.csproj index 8cc310e..e6a6adb 100644 --- a/LightlessSyncServer/LightlessSyncShared/LightlessSyncShared.csproj +++ b/LightlessSyncServer/LightlessSyncShared/LightlessSyncShared.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable @@ -47,7 +47,6 @@ - diff --git a/LightlessSyncServer/LightlessSyncStaticFilesServer/LightlessSyncStaticFilesServer.csproj b/LightlessSyncServer/LightlessSyncStaticFilesServer/LightlessSyncStaticFilesServer.csproj index 0676329..c763b1c 100644 --- a/LightlessSyncServer/LightlessSyncStaticFilesServer/LightlessSyncStaticFilesServer.csproj +++ b/LightlessSyncServer/LightlessSyncStaticFilesServer/LightlessSyncStaticFilesServer.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable