diff --git a/DiscordChatExporter.Core.Models/Guild.cs b/DiscordChatExporter.Core.Models/Guild.cs index 33df8b6f..54f9f44a 100644 --- a/DiscordChatExporter.Core.Models/Guild.cs +++ b/DiscordChatExporter.Core.Models/Guild.cs @@ -5,7 +5,7 @@ using System.Linq; namespace DiscordChatExporter.Core.Models { - // https://discordapp.string.IsNullOrWhiteSpace(com/developers/docs/resources/guild#guild-object + // https://discordapp.com/developers/docs/resources/guild#guild-object public partial class Guild : IHasId { @@ -38,21 +38,20 @@ namespace DiscordChatExporter.Core.Models public partial class Guild { public static string GetUserColor(Guild guild, User user) => - guild.Members.GetValueOrDefault(user.Id, null)?.Roles - ?.Select(r => guild.Roles - .Where(role => r == role.Id) - .FirstOrDefault() - )?.Where(r => r.Color != Color.Black)? - .Aggregate(null, (a, b) => (a?.Position ?? 0) > b.Position? a : b)? - .ColorAsHex ?? ""; + guild.Members.GetValueOrDefault(user.Id, null) + ?.Roles + .Select(r => guild.Roles.FirstOrDefault(role => r == role.Id)) + .Where(r => r != null) + .Where(r => r.Color != Color.Black) + .Aggregate(null, (a, b) => (a?.Position ?? 0) > b.Position ? a : b) + ?.ColorAsHex ?? ""; + public static string GetUserNick(Guild guild, User user) => guild.Members.GetValueOrDefault(user.Id)?.Nick ?? user.Name; - public static string GetIconUrl(string id, string? iconHash) - { - return !string.IsNullOrWhiteSpace(iconHash) + public static string GetIconUrl(string id, string? iconHash) => + !string.IsNullOrWhiteSpace(iconHash) ? $"https://cdn.discordapp.com/icons/{id}/{iconHash}.png" : "https://cdn.discordapp.com/embed/avatars/0.png"; - } public static Guild DirectMessages { get; } = new Guild("@me", "Direct Messages", Array.Empty(), null); } diff --git a/DiscordChatExporter.Core.Models/Member.cs b/DiscordChatExporter.Core.Models/Member.cs index 35b1524d..8f3b9bec 100644 --- a/DiscordChatExporter.Core.Models/Member.cs +++ b/DiscordChatExporter.Core.Models/Member.cs @@ -3,9 +3,12 @@ using System.Linq; namespace DiscordChatExporter.Core.Models { + // https://discordapp.com/developers/docs/resources/guild#guild-member-object + public class Member { public string UserId { get; } + public string? Nick { get; } public IReadOnlyList Roles { get; } diff --git a/DiscordChatExporter.Core.Models/Role.cs b/DiscordChatExporter.Core.Models/Role.cs index af0a4ed8..2a3a6a5e 100644 --- a/DiscordChatExporter.Core.Models/Role.cs +++ b/DiscordChatExporter.Core.Models/Role.cs @@ -1,5 +1,4 @@ - -using System.Drawing; +using System.Drawing; namespace DiscordChatExporter.Core.Models { @@ -13,7 +12,8 @@ namespace DiscordChatExporter.Core.Models public Color Color { get; } - public string ColorAsHex => $"#{(Color.ToArgb() & 0xffffff):X6}"; + public string ColorAsHex => $"#{Color.ToArgb() & 0xffffff:X6}"; + public string ColorAsRgb => $"{Color.R}, {Color.G}, {Color.B}"; public int Position { get; } diff --git a/DiscordChatExporter.Core.Services/DataService.Parsers.cs b/DiscordChatExporter.Core.Services/DataService.Parsers.cs index 53dacaa5..0c972373 100644 --- a/DiscordChatExporter.Core.Services/DataService.Parsers.cs +++ b/DiscordChatExporter.Core.Services/DataService.Parsers.cs @@ -25,7 +25,7 @@ namespace DiscordChatExporter.Core.Services { var userId = ParseUser(json["user"]!).Id; var nick = json["nick"]?.Value(); - var roles = json["roles"]!.Select(jt => jt.Value()).ToArray(); + var roles = (json["roles"] ?? Enumerable.Empty()).Select(j => j.Value()).ToArray(); return new Member(userId, nick, roles); } @@ -35,7 +35,7 @@ namespace DiscordChatExporter.Core.Services var id = json["id"]!.Value(); var name = json["name"]!.Value(); var iconHash = json["icon"]!.Value(); - var roles = json["roles"]!.Select(ParseRole).ToList(); + var roles = (json["roles"] ?? Enumerable.Empty()).Select(ParseRole).ToArray(); return new Guild(id, name, roles, iconHash); } @@ -205,7 +205,7 @@ namespace DiscordChatExporter.Core.Services // Get author var author = ParseUser(json["author"]!); - + // Get attachments var attachments = (json["attachments"] ?? Enumerable.Empty()).Select(ParseAttachment).ToArray(); diff --git a/DiscordChatExporter.Core.Services/DataService.cs b/DiscordChatExporter.Core.Services/DataService.cs index 4ea03f7c..1d48327a 100644 --- a/DiscordChatExporter.Core.Services/DataService.cs +++ b/DiscordChatExporter.Core.Services/DataService.cs @@ -40,11 +40,12 @@ namespace DiscordChatExporter.Core.Services }, (response, timespan, retryCount, context) => Task.CompletedTask); } - + private async Task GetApiResponseAsync(AuthToken token, string route) { return (await GetApiResponseAsync(token, route, true))!; } + private async Task GetApiResponseAsync(AuthToken token, string route, bool errorOnFail) { using var response = await _httpPolicy.ExecuteAsync(async () => @@ -61,7 +62,7 @@ namespace DiscordChatExporter.Core.Services // We throw our own exception here because default one doesn't have status code if (!response.IsSuccessStatusCode) { - if(errorOnFail) throw new HttpErrorStatusCodeException(response.StatusCode, response.ReasonPhrase); + if (errorOnFail) throw new HttpErrorStatusCodeException(response.StatusCode, response.ReasonPhrase); else return null; } @@ -84,7 +85,7 @@ namespace DiscordChatExporter.Core.Services public async Task GetGuildMemberAsync(AuthToken token, string guildId, string userId) { var response = await GetApiResponseAsync(token, $"guilds/{guildId}/members/{userId}", false); - if(response == null) return null; + if (response == null) return null; var member = ParseMember(response); return member; @@ -113,10 +114,11 @@ namespace DiscordChatExporter.Core.Services if (!response.HasValues) yield break; - foreach (var guild in response.Select(ParseGuild)) + // Get full guild object + foreach (var guildId in response.Select(j => j["id"]!.Value())) { - yield return guild; - afterId = guild.Id; + yield return await GetGuildAsync(token, guildId); + afterId = guildId; } } }