diff --git a/LightlessSyncServer/LightlessSyncServer/Controllers/GroupController.cs b/LightlessSyncServer/LightlessSyncServer/Controllers/GroupController.cs new file mode 100644 index 0000000..e77e094 --- /dev/null +++ b/LightlessSyncServer/LightlessSyncServer/Controllers/GroupController.cs @@ -0,0 +1,56 @@ +using LightlessSync.API.Dto.Group; +using LightlessSync.API.Routes; +using LightlessSyncShared.Data; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace LightlessSyncServer.Controllers; + +[Route(LightlessAuth.Group)] +[Authorize(Policy = "Internal")] +public class GroupController : Controller +{ + protected readonly ILogger Logger; + protected readonly IDbContextFactory LightlessDbContextFactory; + + public GroupController(ILogger logger, IDbContextFactory lightlessDbContext) + { + Logger = logger; + LightlessDbContextFactory = lightlessDbContext; + } + + [Route(LightlessAuth.Disable_Profile)] + [HttpPost] + public async Task DisableGroupProfile([FromBody] GroupProfileAvailabilityRequest request) + { + using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); + + Logger.LogInformation("Disabling profile for group with GID {GID}", request.GID); + + var group = await dbContext.GroupProfiles.FirstOrDefaultAsync(f => f.GroupGID == request.GID); + if (group != null) + { + group.ProfileDisabled = true; + } + + await dbContext.SaveChangesAsync(); + } + + [Route(LightlessAuth.Enable_Profile)] + [HttpPost] + public async Task EnableGroupProfile([FromBody] GroupProfileAvailabilityRequest request) + { + using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); + + Logger.LogInformation("Disabling profile for group with GID {GID}", request.GID); + + var group = await dbContext.GroupProfiles.FirstOrDefaultAsync(f => f.GroupGID == request.GID); + if (group != null) + { + group.ProfileDisabled = false; + } + + await dbContext.SaveChangesAsync(); + } +} \ No newline at end of file diff --git a/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs b/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs index 0084566..19917bf 100644 --- a/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs +++ b/LightlessSyncServer/LightlessSyncServer/Controllers/UserController.cs @@ -5,7 +5,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -namespace LightlessSyncAuthService.Controllers; +namespace LightlessSyncServer.Controllers; [Route(LightlessAuth.User)] [Authorize(Policy = "Internal")] @@ -96,4 +96,38 @@ public class UserController : Controller await dbContext.SaveChangesAsync(); } + + [Route(LightlessAuth.Disable_Profile)] + [HttpPost] + public async Task DisableGroupProfile([FromBody] UserProfileAvailabilityRequest request) + { + using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); + + Logger.LogInformation("Disabling profile for user with uid {UID}", request.UID); + + var user = await dbContext.UserProfileData.FirstOrDefaultAsync(f => f.UserUID == request.UID); + if (user != null) + { + user.ProfileDisabled = true; + } + + await dbContext.SaveChangesAsync(); + } + + [Route(LightlessAuth.Enable_Profile)] + [HttpPost] + public async Task EnableGroupProfile([FromBody] UserProfileAvailabilityRequest request) + { + using var dbContext = await LightlessDbContextFactory.CreateDbContextAsync(); + + Logger.LogInformation("Enabling profile for user with uid {UID}", request.UID); + + var user = await dbContext.UserProfileData.FirstOrDefaultAsync(f => f.UserUID == request.UID); + if (user != null) + { + user.ProfileDisabled = false; + } + + await dbContext.SaveChangesAsync(); + } } \ No newline at end of file diff --git a/LightlessSyncServer/LightlessSyncServer/Startup.cs b/LightlessSyncServer/LightlessSyncServer/Startup.cs index 551715a..b724a54 100644 --- a/LightlessSyncServer/LightlessSyncServer/Startup.cs +++ b/LightlessSyncServer/LightlessSyncServer/Startup.cs @@ -1,6 +1,5 @@ using AspNetCoreRateLimit; using LightlessSync.API.SignalR; -using LightlessSyncAuthService.Controllers; using LightlessSyncServer.Controllers; using LightlessSyncServer.Configuration; using LightlessSyncServer.Hubs; @@ -73,7 +72,7 @@ public class Startup a.FeatureProviders.Remove(a.FeatureProviders.OfType().First()); if (lightlessConfig.GetValue(nameof(ServerConfiguration.MainServerAddress), defaultValue: null) == null) { - a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(LightlessServerConfigurationController), typeof(LightlessBaseConfigurationController), typeof(ClientMessageController), typeof(UserController))); + a.FeatureProviders.Add(new AllowedControllersFeatureProvider(typeof(LightlessServerConfigurationController), typeof(LightlessBaseConfigurationController), typeof(ClientMessageController), typeof(UserController), typeof(GroupController))); } else { diff --git a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs index 48d1c03..5d531a9 100644 --- a/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs +++ b/LightlessSyncServer/LightlessSyncServices/Discord/MareModule.cs @@ -1,15 +1,17 @@ using Discord; using Discord.Interactions; +using LightlessSync.API.Data.Enum; +using LightlessSync.API.Dto.Group; +using LightlessSync.API.Dto.User; using LightlessSyncShared.Data; +using LightlessSyncShared.Models; +using LightlessSyncShared.Services; +using LightlessSyncShared.Utils; +using LightlessSyncShared.Utils.Configuration; using Microsoft.EntityFrameworkCore; using Prometheus; -using LightlessSyncShared.Models; -using LightlessSyncShared.Utils; -using LightlessSyncShared.Services; using StackExchange.Redis; -using LightlessSync.API.Data.Enum; -using LightlessSyncShared.Utils.Configuration; -using LightlessSync.API.Dto.User; +using System.Net.Http.Json; namespace LightlessSyncServices.Discord; @@ -43,7 +45,56 @@ public class LightlessModule : InteractionModuleBase { EmbedBuilder eb = new(); - eb = await HandleUserInfo(eb, Context.User.Id, secondaryUid, discordUser?.Id ?? null, uid); + 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); + + string uidToGet = await GetUserUID(db, secondaryUid, discordUser?.Id ?? null, uid).ConfigureAwait(false); + var profileData = await GetUserProfileData(db, uidToGet).ConfigureAwait(false); + 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"); + await RespondWithFilesAsync( + new[] { new FileAttachment(profileImgStream, "profileimage.png"), new FileAttachment(bannerImgStream, "bannerimage.png") }, + embeds: new[] { eb.Build() }, + ephemeral: true).ConfigureAwait(false); + } + else + { + await RespondAsync( + embeds: new[] { eb.Build() }, + ephemeral: true).ConfigureAwait(false); + } + } + } + catch (Exception ex) + { + EmbedBuilder eb = new(); + eb.WithTitle("An error occured"); + eb.WithDescription("Please report this error to bug-reports: " + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace + Environment.NewLine); + + await RespondAsync(embeds: new Embed[] { eb.Build() }, ephemeral: true).ConfigureAwait(false); + } + } + + [SlashCommand("groupinfo", "Shows you your group profile information")] + public async Task GroupInfo([Summary("gid", "ADMIN ONLY: GID to check for")] string? uid = null) + { + _logger.LogInformation("SlashCommand:{userId}:{Method}", + Context.Interaction.User.Id, nameof(GroupInfo)); + + try + { + EmbedBuilder eb = new(); + + //eb = await HandleUserInfo(eb, Context.User.Id, secondaryUid, discordUser?.Id ?? null, uid); await RespondAsync(embeds: new[] { eb.Build() }, ephemeral: true).ConfigureAwait(false); } @@ -110,10 +161,10 @@ public class LightlessModule : InteractionModuleBase var testUri = new Uri(_lightlessServicesConfiguration.GetValue (nameof(ServicesConfiguration.MainServerAddress)), "/msgc/sendMessage"); - await c.PostAsJsonAsync( + using (await c.PostAsJsonAsync( new Uri(_lightlessServicesConfiguration.GetValue(nameof(ServicesConfiguration.MainServerAddress)), "/msgc/sendMessage"), new ClientMessage(messageType, message, uid ?? string.Empty) - ).ConfigureAwait(false); + ).ConfigureAwait(false)) { } var discordChannelForMessages = _lightlessServicesConfiguration.GetValueOrDefault(nameof(ServicesConfiguration.DiscordChannelForMessages), null); if (uid == null && discordChannelForMessages != null) @@ -146,20 +197,47 @@ public class LightlessModule : InteractionModuleBase } } - [SlashCommand("unbanbydiscord", "ADMIN ONLY: Unban a user by their discord ID")] - public async Task UnbanByDiscord([Summary("discord_id", "Discord ID to unban")] string discordId) + [SlashCommand("serviceunban", "ADMIN ONLY: Unban a user by their discord ID or user ID [CHOOSE ONE ONLY]")] + public async Task ServiceUnban( + [Summary("discord_id", "Discord ID to unban")] string? discordId = null, + [Summary("uid", "UID to unban")] string? uid = null + ) { _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", - Context.Interaction.User.Id, nameof(UnbanByDiscord), - string.Join(",", new[] { $"{nameof(discordId)}:{discordId}" })); + Context.Interaction.User.Id, nameof(ServiceUnban), + string.Join(",", new[] { $"{nameof(discordId)}:{discordId}", $"{nameof(uid)}:{uid}" })); + try { using HttpClient c = new HttpClient(); - + c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); - await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue - (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanDiscord"), new UnbanRequest(string.Empty, discordId)) - .ConfigureAwait(false); + + string endpoint; + UnbanRequest unbanRequest; + + if (!string.IsNullOrEmpty(uid)) + { + endpoint = "/user/unbanUID"; + unbanRequest = new UnbanRequest(uid, string.Empty); + } + else if (!string.IsNullOrEmpty(discordId)) + { + endpoint = "/user/unbanDiscord"; + unbanRequest = new UnbanRequest(string.Empty, discordId); + } + else + { + await RespondAsync("You must provide either a UID or Discord ID.", ephemeral: true).ConfigureAwait(false); + return; + } + + using (await c.PostAsJsonAsync( + new Uri(_lightlessServicesConfiguration.GetValue(nameof(ServicesConfiguration.MainServerAddress)), endpoint), + unbanRequest).ConfigureAwait(false)) + { + } + var discordChannelForMessages = _lightlessServicesConfiguration.GetValueOrDefault(nameof(ServicesConfiguration.DiscordChannelForMessages), null); if (discordChannelForMessages != null) { @@ -168,10 +246,12 @@ public class LightlessModule : InteractionModuleBase { var embedColor = Color.Blue; + String idToUse = !string.IsNullOrEmpty(uid) ? uid : discordId; + EmbedBuilder eb = new(); eb.WithTitle("Unban Alert!"); eb.WithColor(embedColor); - eb.WithDescription(discordId + " has been unbanned"); + eb.WithDescription(idToUse + " has been unbanned"); await discordChannel.SendMessageAsync(embed: eb.Build()).ConfigureAwait(false); } @@ -188,64 +268,20 @@ public class LightlessModule : InteractionModuleBase } } - [SlashCommand("unbanbyuid", "ADMIN ONLY: Unban a user by their uid")] - public async Task UnbanByUID([Summary("uid", "uid to unban")] string uid) + [SlashCommand("serviceban", "ADMIN ONLY: ban a user by their uid")] + public async Task ServiceBan([Summary("uid", "uid to ban")] string uid) { _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", - Context.Interaction.User.Id, nameof(UnbanByUID), - string.Join(",", new[] { $"{nameof(uid)}:{uid}" })); - try - { - using HttpClient c = new HttpClient(); - var testUri = new Uri(_lightlessServicesConfiguration.GetValue - (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanDiscord"); - - c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); - await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue - (nameof(ServicesConfiguration.MainServerAddress)), "/user/unbanUID"), new UnbanRequest(uid, string.Empty)) - .ConfigureAwait(false); - var discordChannelForMessages = _lightlessServicesConfiguration.GetValueOrDefault(nameof(ServicesConfiguration.DiscordChannelForMessages), null); - if (discordChannelForMessages != null) - { - var discordChannel = await Context.Guild.GetChannelAsync(discordChannelForMessages.Value).ConfigureAwait(false) as IMessageChannel; - if (discordChannel != null) - { - var embedColor = Color.Blue; - - EmbedBuilder eb = new(); - eb.WithTitle("Unban Alert!"); - eb.WithColor(embedColor); - eb.WithDescription(uid + " has been unbanned"); - - await discordChannel.SendMessageAsync(embed: eb.Build()).ConfigureAwait(false); - } - } - - await RespondAsync("Message sent", ephemeral: true).ConfigureAwait(false); - } - catch (Exception ex) - { - EmbedBuilder eb = new(); - eb.WithTitle("An error occured"); - eb.WithDescription("Please report this: " + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace + Environment.NewLine); - await RespondAsync(embeds: new Embed[] { eb.Build() }, ephemeral: true).ConfigureAwait(false); - } - } - - [SlashCommand("markforban", "ADMIN ONLY: ban a user by their uid")] - public async Task MarkUidForBan([Summary("uid", "uid to ban")] string uid) - { - _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", - Context.Interaction.User.Id, nameof(MarkUidForBan), + Context.Interaction.User.Id, nameof(ServiceBan), string.Join(",", new[] { $"{nameof(uid)}:{uid}" })); try { using HttpClient c = new HttpClient(); c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); - await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue + using (await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue (nameof(ServicesConfiguration.MainServerAddress)), "/user/ban"), new BanRequest(uid)) - .ConfigureAwait(false); + .ConfigureAwait(false)) { } var discordChannelForMessages = _lightlessServicesConfiguration.GetValueOrDefault(nameof(ServicesConfiguration.DiscordChannelForMessages), null); if (discordChannelForMessages != null) { @@ -274,6 +310,100 @@ public class LightlessModule : InteractionModuleBase } } + [SlashCommand("toggleuserprofile", "ADMIN ONLY: disable a user profile by their uid")] + public async Task ToggleUserProfile( + [Summary("uid", "uid to disable")] string uid, + [Summary("toggle", "Enable or Disable the profile")] + [Choice("Enable", "Enable")] + [Choice("Disable", "Disable")] string toggle + ) + { + _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", + Context.Interaction.User.Id, nameof(ToggleUserProfile), + string.Join(",", new[] { $"{nameof(uid)}:{uid}" })); + try + { + using HttpClient c = new HttpClient(); + c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); + string endpoint = string.Equals(toggle, "Enable", StringComparison.Ordinal) ? "/user/enableProfile" : "/user/disableProfile"; + using (await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue + (nameof(ServicesConfiguration.MainServerAddress)), endpoint), new UserProfileAvailabilityRequest(uid)) + .ConfigureAwait(false)) { } + var discordChannelForMessages = _lightlessServicesConfiguration.GetValueOrDefault(nameof(ServicesConfiguration.DiscordChannelForMessages), null); + if (discordChannelForMessages != null) + { + var discordChannel = await Context.Guild.GetChannelAsync(discordChannelForMessages.Value).ConfigureAwait(false) as IMessageChannel; + if (discordChannel != null) + { + var embedColor = Color.Blue; + var action = string.Equals(toggle, "Enable", StringComparison.Ordinal) ? "enabled" : "disabled"; + + EmbedBuilder eb = new(); + eb.WithTitle($"Profile {action}"); + eb.WithColor(embedColor); + eb.WithDescription($"{uid}'s profile has been {action}"); + + await discordChannel.SendMessageAsync(embed: eb.Build()).ConfigureAwait(false); + } + } + await RespondAsync("Message sent", ephemeral: true).ConfigureAwait(false); + } + catch (Exception ex) + { + EmbedBuilder eb = new(); + eb.WithTitle("An error occured"); + eb.WithDescription("Please report this: " + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace + Environment.NewLine); + await RespondAsync(embeds: new Embed[] { eb.Build() }, ephemeral: true).ConfigureAwait(false); + } + } + + [SlashCommand("togglegroupprofile", "ADMIN ONLY: toggle a group profile by their gid")] + public async Task ToggleGroupProfile( + [Summary("gid", "gid to disable")] string gid, + [Summary("toggle", "Enable or Disable the profile")] + [Choice("Enable", "Enable")] + [Choice("Disable", "Disable")] string toggle + ) + { + _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", + Context.Interaction.User.Id, nameof(ToggleUserProfile), + string.Join(",", new[] { $"{nameof(gid)}:{gid}" })); + try + { + using HttpClient c = new HttpClient(); + c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _serverTokenGenerator.Token); + string endpoint = string.Equals(toggle, "Enable", StringComparison.Ordinal) ? "/group/enableProfile" : "/group/disableProfile"; + using (await c.PostAsJsonAsync(new Uri(_lightlessServicesConfiguration.GetValue + (nameof(ServicesConfiguration.MainServerAddress)), endpoint), new GroupProfileAvailabilityRequest(gid)) + .ConfigureAwait(false)) { } + var discordChannelForMessages = _lightlessServicesConfiguration.GetValueOrDefault(nameof(ServicesConfiguration.DiscordChannelForMessages), null); + if (discordChannelForMessages != null) + { + var discordChannel = await Context.Guild.GetChannelAsync(discordChannelForMessages.Value).ConfigureAwait(false) as IMessageChannel; + if (discordChannel != null) + { + var embedColor = Color.Blue; + var action = string.Equals(toggle, "Enable", StringComparison.Ordinal) ? "enabled" : "disabled"; + + EmbedBuilder eb = new(); + eb.WithTitle($"Profile {action}"); + eb.WithColor(embedColor); + eb.WithDescription($"{gid}'s profile has been {action}"); + + await discordChannel.SendMessageAsync(embed: eb.Build()).ConfigureAwait(false); + } + } + await RespondAsync("Message sent", ephemeral: true).ConfigureAwait(false); + } + catch (Exception ex) + { + EmbedBuilder eb = new(); + eb.WithTitle("An error occured"); + eb.WithDescription("Please report this: " + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace + Environment.NewLine); + await RespondAsync(embeds: new Embed[] { eb.Build() }, ephemeral: true).ConfigureAwait(false); + } + } + public async Task HandleUserAdd(string desiredUid, ulong discordUserId) { var embed = new EmbedBuilder(); @@ -319,11 +449,9 @@ public class LightlessModule : InteractionModuleBase return embed.Build(); } - private async Task HandleUserInfo(EmbedBuilder eb, ulong id, string? secondaryUserUid = null, ulong? optionalUser = null, string? uid = null) + private async Task HandleUserInfo(EmbedBuilder eb, LightlessDbContext db, ulong id, string? secondaryUserUid = null, ulong? optionalUser = null, string? uid = null) { bool showForSecondaryUser = secondaryUserUid != null; - using var scope = _services.CreateScope(); - await using var db = scope.ServiceProvider.GetRequiredService(); var primaryUser = await db.LodeStoneAuth.Include(u => u.User).SingleOrDefaultAsync(u => u.DiscordId == id).ConfigureAwait(false); @@ -382,6 +510,7 @@ public class LightlessModule : InteractionModuleBase var auth = await db.Auth.Include(u => u.PrimaryUser).SingleOrDefaultAsync(u => u.UserUID == dbUser.UID).ConfigureAwait(false); var groups = await db.Groups.Where(g => g.OwnerUID == dbUser.UID).ToListAsync().ConfigureAwait(false); var groupsJoined = await db.GroupPairs.Where(g => g.GroupUserUID == dbUser.UID).ToListAsync().ConfigureAwait(false); + 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"); @@ -404,6 +533,14 @@ public class LightlessModule : InteractionModuleBase eb.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); @@ -426,4 +563,62 @@ public class LightlessModule : InteractionModuleBase return eb; } + + private async Task GetUserUID(LightlessDbContext db, string? secondaryUserUid = null, ulong? optionalUser = null, string? uid = null) + { + var primaryUser = await db.LodeStoneAuth.Include(u => u.User).SingleOrDefaultAsync(u => u.DiscordId == Context.User.Id).ConfigureAwait(false); + ulong userToCheckForDiscordId = Context.User.Id; + + if ((optionalUser != null || uid != null)) + { + LodeStoneAuth userInDb = null; + if (optionalUser != null) + { + userInDb = await db.LodeStoneAuth.Include(u => u.User).SingleOrDefaultAsync(u => u.DiscordId == optionalUser).ConfigureAwait(false); + } + else if (uid != null) + { + userInDb = await db.LodeStoneAuth.Include(u => u.User).SingleOrDefaultAsync(u => u.User.UID == uid || u.User.Alias == uid).ConfigureAwait(false); + } + if (userInDb == null) + { + throw new Exception("The Discord user has no valid Lightless account"); + } + userToCheckForDiscordId = userInDb.DiscordId; + } + var lodestoneUser = await db.LodeStoneAuth.Include(u => u.User).SingleOrDefaultAsync(u => u.DiscordId == userToCheckForDiscordId).ConfigureAwait(false); + var dbUser = lodestoneUser.User; + if (secondaryUserUid != null) + { + dbUser = (await db.Auth.Include(u => u.User).SingleOrDefaultAsync(u => u.PrimaryUserUID == dbUser.UID && u.UserUID == secondaryUserUid))?.User; + if (dbUser == null) + { + throw new Exception($"A secondary UID {secondaryUserUid} was not found attached to your primary UID {primaryUser.User.UID}."); + } + } + return dbUser.UID; + } + private byte[] GetProfileImage(UserProfileData profile) + { + if (profile != null && profile.Base64ProfileImage != null && profile.Base64ProfileImage.Length > 0) + { + return Convert.FromBase64String(profile.Base64ProfileImage); + } + return Array.Empty(); + } + + private byte[] GetBannerImage(UserProfileData profile) + { + if (profile != null && profile.Base64BannerImage != null && profile.Base64BannerImage.Length > 0) + { + return Convert.FromBase64String(profile.Base64BannerImage); + } + return Array.Empty(); + } + + private async Task GetUserProfileData(LightlessDbContext db, string uid) + { + var profile = await db.UserProfileData.Where(u => u.UserUID == uid).SingleOrDefaultAsync().ConfigureAwait(false); + return profile; + } }