Fix nullability errors

This commit is contained in:
Tyrrrz 2021-11-08 23:16:37 +02:00
parent f456297881
commit 214d5e3bdb
20 changed files with 72 additions and 48 deletions

View file

@ -3,7 +3,7 @@
"isRoot": true, "isRoot": true,
"tools": { "tools": {
"xamlstyler.console": { "xamlstyler.console": {
"version": "3.2003.9", "version": "3.2008.4",
"commands": [ "commands": [
"xstyler" "xstyler"
] ]

View file

@ -58,11 +58,11 @@ namespace DiscordChatExporter.Core.Discord.Data
{ {
public static Attachment Parse(JsonElement json) public static Attachment Parse(JsonElement json)
{ {
var id = json.GetProperty("id").GetString().Pipe(Snowflake.Parse); var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse);
var url = json.GetProperty("url").GetString(); var url = json.GetProperty("url").GetNonWhiteSpaceString();
var width = json.GetPropertyOrNull("width")?.GetInt32(); var width = json.GetPropertyOrNull("width")?.GetInt32();
var height = json.GetPropertyOrNull("height")?.GetInt32(); var height = json.GetPropertyOrNull("height")?.GetInt32();
var fileName = json.GetProperty("filename").GetString(); var fileName = json.GetProperty("filename").GetNonWhiteSpaceString();
var fileSize = json.GetProperty("size").GetInt64().Pipe(FileSize.FromBytes); var fileSize = json.GetProperty("size").GetInt64().Pipe(FileSize.FromBytes);
return new Attachment(id, url, fileName, width, height, fileSize); return new Attachment(id, url, fileName, width, height, fileSize);

View file

@ -74,14 +74,14 @@ namespace DiscordChatExporter.Core.Discord.Data
public static Channel Parse(JsonElement json, ChannelCategory? category = null, int? position = null) public static Channel Parse(JsonElement json, ChannelCategory? category = null, int? position = null)
{ {
var id = json.GetProperty("id").GetString().Pipe(Snowflake.Parse); var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse);
var guildId = json.GetPropertyOrNull("guild_id")?.GetString().Pipe(Snowflake.Parse); var guildId = json.GetPropertyOrNull("guild_id")?.GetNonWhiteSpaceString().Pipe(Snowflake.Parse);
var topic = json.GetPropertyOrNull("topic")?.GetString(); var topic = json.GetPropertyOrNull("topic")?.GetStringOrNull();
var kind = (ChannelKind) json.GetProperty("type").GetInt32(); var kind = (ChannelKind) json.GetProperty("type").GetInt32();
var name = var name =
// Guild channel // Guild channel
json.GetPropertyOrNull("name")?.GetString() ?? json.GetPropertyOrNull("name")?.GetStringOrNull() ??
// DM channel // DM channel
json.GetPropertyOrNull("recipients")?.EnumerateArray().Select(User.Parse).Select(u => u.Name).JoinToString(", ") ?? json.GetPropertyOrNull("recipients")?.EnumerateArray().Select(User.Parse).Select(u => u.Name).JoinToString(", ") ??
// Fallback // Fallback

View file

@ -31,10 +31,10 @@ namespace DiscordChatExporter.Core.Discord.Data
public static ChannelCategory Parse(JsonElement json, int? position = null) public static ChannelCategory Parse(JsonElement json, int? position = null)
{ {
var id = json.GetProperty("id").GetString().Pipe(Snowflake.Parse); var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse);
var name = var name =
json.GetPropertyOrNull("name")?.GetString() ?? json.GetPropertyOrNull("name")?.GetStringOrNull() ??
id.ToString(); id.ToString();
return new ChannelCategory( return new ChannelCategory(

View file

@ -70,11 +70,11 @@ namespace DiscordChatExporter.Core.Discord.Data.Embeds
{ {
public static Embed Parse(JsonElement json) public static Embed Parse(JsonElement json)
{ {
var title = json.GetPropertyOrNull("title")?.GetString(); var title = json.GetPropertyOrNull("title")?.GetStringOrNull();
var url = json.GetPropertyOrNull("url")?.GetString(); var url = json.GetPropertyOrNull("url")?.GetStringOrNull();
var timestamp = json.GetPropertyOrNull("timestamp")?.GetDateTimeOffset(); var timestamp = json.GetPropertyOrNull("timestamp")?.GetDateTimeOffset();
var color = json.GetPropertyOrNull("color")?.GetInt32().Pipe(System.Drawing.Color.FromArgb).ResetAlpha(); var color = json.GetPropertyOrNull("color")?.GetInt32().Pipe(System.Drawing.Color.FromArgb).ResetAlpha();
var description = json.GetPropertyOrNull("description")?.GetString(); var description = json.GetPropertyOrNull("description")?.GetStringOrNull();
var author = json.GetPropertyOrNull("author")?.Pipe(EmbedAuthor.Parse); var author = json.GetPropertyOrNull("author")?.Pipe(EmbedAuthor.Parse);
var thumbnail = json.GetPropertyOrNull("thumbnail")?.Pipe(EmbedImage.Parse); var thumbnail = json.GetPropertyOrNull("thumbnail")?.Pipe(EmbedImage.Parse);

View file

@ -31,10 +31,10 @@ namespace DiscordChatExporter.Core.Discord.Data.Embeds
{ {
public static EmbedAuthor Parse(JsonElement json) public static EmbedAuthor Parse(JsonElement json)
{ {
var name = json.GetPropertyOrNull("name")?.GetString(); var name = json.GetPropertyOrNull("name")?.GetStringOrNull();
var url = json.GetPropertyOrNull("url")?.GetString(); var url = json.GetPropertyOrNull("url")?.GetStringOrNull();
var iconUrl = json.GetPropertyOrNull("icon_url")?.GetString(); var iconUrl = json.GetPropertyOrNull("icon_url")?.GetStringOrNull();
var iconProxyUrl = json.GetPropertyOrNull("proxy_icon_url")?.GetString(); var iconProxyUrl = json.GetPropertyOrNull("proxy_icon_url")?.GetStringOrNull();
return new EmbedAuthor(name, url, iconUrl, iconProxyUrl); return new EmbedAuthor(name, url, iconUrl, iconProxyUrl);
} }

View file

@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Text.Json; using System.Text.Json;
using DiscordChatExporter.Core.Utils.Extensions;
using JsonExtensions.Reading; using JsonExtensions.Reading;
namespace DiscordChatExporter.Core.Discord.Data.Embeds namespace DiscordChatExporter.Core.Discord.Data.Embeds
@ -28,8 +29,8 @@ namespace DiscordChatExporter.Core.Discord.Data.Embeds
{ {
public static EmbedField Parse(JsonElement json) public static EmbedField Parse(JsonElement json)
{ {
var name = json.GetProperty("name").GetString(); var name = json.GetProperty("name").GetNonWhiteSpaceString();
var value = json.GetProperty("value").GetString(); var value = json.GetProperty("value").GetNonWhiteSpaceString();
var isInline = json.GetPropertyOrNull("inline")?.GetBoolean() ?? false; var isInline = json.GetPropertyOrNull("inline")?.GetBoolean() ?? false;
return new EmbedField(name, value, isInline); return new EmbedField(name, value, isInline);

View file

@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Text.Json; using System.Text.Json;
using DiscordChatExporter.Core.Utils.Extensions;
using JsonExtensions.Reading; using JsonExtensions.Reading;
namespace DiscordChatExporter.Core.Discord.Data.Embeds namespace DiscordChatExporter.Core.Discord.Data.Embeds
@ -28,9 +29,9 @@ namespace DiscordChatExporter.Core.Discord.Data.Embeds
{ {
public static EmbedFooter Parse(JsonElement json) public static EmbedFooter Parse(JsonElement json)
{ {
var text = json.GetProperty("text").GetString(); var text = json.GetProperty("text").GetNonWhiteSpaceString();
var iconUrl = json.GetPropertyOrNull("icon_url")?.GetString(); var iconUrl = json.GetPropertyOrNull("icon_url")?.GetStringOrNull();
var iconProxyUrl = json.GetPropertyOrNull("proxy_icon_url")?.GetString(); var iconProxyUrl = json.GetPropertyOrNull("proxy_icon_url")?.GetStringOrNull();
return new EmbedFooter(text, iconUrl, iconProxyUrl); return new EmbedFooter(text, iconUrl, iconProxyUrl);
} }

View file

@ -27,8 +27,8 @@ namespace DiscordChatExporter.Core.Discord.Data.Embeds
{ {
public static EmbedImage Parse(JsonElement json) public static EmbedImage Parse(JsonElement json)
{ {
var url = json.GetPropertyOrNull("url")?.GetString(); var url = json.GetPropertyOrNull("url")?.GetStringOrNull();
var proxyUrl = json.GetPropertyOrNull("proxy_url")?.GetString(); var proxyUrl = json.GetPropertyOrNull("proxy_url")?.GetStringOrNull();
var width = json.GetPropertyOrNull("width")?.GetInt32(); var width = json.GetPropertyOrNull("width")?.GetInt32();
var height = json.GetPropertyOrNull("height")?.GetInt32(); var height = json.GetPropertyOrNull("height")?.GetInt32();

View file

@ -64,8 +64,8 @@ namespace DiscordChatExporter.Core.Discord.Data
public static Emoji Parse(JsonElement json) public static Emoji Parse(JsonElement json)
{ {
var id = json.GetPropertyOrNull("id")?.GetString(); var id = json.GetPropertyOrNull("id")?.GetNonWhiteSpaceString();
var name = json.GetProperty("name").GetString(); var name = json.GetProperty("name").GetNonWhiteSpaceString();
var isAnimated = json.GetPropertyOrNull("animated")?.GetBoolean() ?? false; var isAnimated = json.GetPropertyOrNull("animated")?.GetBoolean() ?? false;
var imageUrl = GetImageUrl(id, name, isAnimated); var imageUrl = GetImageUrl(id, name, isAnimated);

View file

@ -2,6 +2,7 @@
using System.Text.Json; using System.Text.Json;
using DiscordChatExporter.Core.Discord.Data.Common; using DiscordChatExporter.Core.Discord.Data.Common;
using DiscordChatExporter.Core.Utils.Extensions; using DiscordChatExporter.Core.Utils.Extensions;
using JsonExtensions.Reading;
namespace DiscordChatExporter.Core.Discord.Data namespace DiscordChatExporter.Core.Discord.Data
{ {
@ -41,9 +42,9 @@ namespace DiscordChatExporter.Core.Discord.Data
public static Guild Parse(JsonElement json) public static Guild Parse(JsonElement json)
{ {
var id = json.GetProperty("id").GetString().Pipe(Snowflake.Parse); var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse);
var name = json.GetProperty("name").GetString(); var name = json.GetProperty("name").GetNonWhiteSpaceString();
var iconHash = json.GetProperty("icon").GetString(); var iconHash = json.GetPropertyOrNull("icon")?.GetStringOrNull();
var iconUrl = !string.IsNullOrWhiteSpace(iconHash) var iconUrl = !string.IsNullOrWhiteSpace(iconHash)
? GetIconUrl(id, iconHash) ? GetIconUrl(id, iconHash)

View file

@ -42,10 +42,10 @@ namespace DiscordChatExporter.Core.Discord.Data
public static Member Parse(JsonElement json) public static Member Parse(JsonElement json)
{ {
var user = json.GetProperty("user").Pipe(User.Parse); var user = json.GetProperty("user").Pipe(User.Parse);
var nick = json.GetPropertyOrNull("nick")?.GetString(); var nick = json.GetPropertyOrNull("nick")?.GetStringOrNull();
var roleIds = var roleIds =
json.GetPropertyOrNull("roles")?.EnumerateArray().Select(j => j.GetString()).Select(Snowflake.Parse).ToArray() ?? json.GetPropertyOrNull("roles")?.EnumerateArray().Select(j => j.GetNonWhiteSpaceString()).Select(Snowflake.Parse).ToArray() ??
Array.Empty<Snowflake>(); Array.Empty<Snowflake>();
return new Member( return new Member(

View file

@ -81,7 +81,7 @@ namespace DiscordChatExporter.Core.Discord.Data
{ {
public static Message Parse(JsonElement json) public static Message Parse(JsonElement json)
{ {
var id = json.GetProperty("id").GetString().Pipe(Snowflake.Parse); var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse);
var author = json.GetProperty("author").Pipe(User.Parse); var author = json.GetProperty("author").Pipe(User.Parse);
var timestamp = json.GetProperty("timestamp").GetDateTimeOffset(); var timestamp = json.GetProperty("timestamp").GetDateTimeOffset();
var editedTimestamp = json.GetPropertyOrNull("edited_timestamp")?.GetDateTimeOffset(); var editedTimestamp = json.GetPropertyOrNull("edited_timestamp")?.GetDateTimeOffset();
@ -101,7 +101,7 @@ namespace DiscordChatExporter.Core.Discord.Data
MessageKind.ChannelIconChange => "Changed the channel icon.", MessageKind.ChannelIconChange => "Changed the channel icon.",
MessageKind.ChannelPinnedMessage => "Pinned a message.", MessageKind.ChannelPinnedMessage => "Pinned a message.",
MessageKind.GuildMemberJoin => "Joined the server.", MessageKind.GuildMemberJoin => "Joined the server.",
_ => json.GetPropertyOrNull("content")?.GetString() ?? "" _ => json.GetPropertyOrNull("content")?.GetStringOrNull() ?? ""
}; };
var attachments = var attachments =

View file

@ -29,9 +29,9 @@ namespace DiscordChatExporter.Core.Discord.Data
{ {
public static MessageReference Parse(JsonElement json) public static MessageReference Parse(JsonElement json)
{ {
var messageId = json.GetPropertyOrNull("message_id")?.GetString().Pipe(Snowflake.Parse); var messageId = json.GetPropertyOrNull("message_id")?.GetStringOrNull()?.Pipe(Snowflake.Parse);
var channelId = json.GetPropertyOrNull("channel_id")?.GetString().Pipe(Snowflake.Parse); var channelId = json.GetPropertyOrNull("channel_id")?.GetStringOrNull()?.Pipe(Snowflake.Parse);
var guildId = json.GetPropertyOrNull("guild_id")?.GetString().Pipe(Snowflake.Parse); var guildId = json.GetPropertyOrNull("guild_id")?.GetStringOrNull()?.Pipe(Snowflake.Parse);
return new MessageReference(messageId, channelId, guildId); return new MessageReference(messageId, channelId, guildId);
} }

View file

@ -38,8 +38,8 @@ namespace DiscordChatExporter.Core.Discord.Data
{ {
public static Role Parse(JsonElement json) public static Role Parse(JsonElement json)
{ {
var id = json.GetProperty("id").GetString().Pipe(Snowflake.Parse); var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse);
var name = json.GetProperty("name").GetString(); var name = json.GetProperty("name").GetNonWhiteSpaceString();
var position = json.GetProperty("position").GetInt32(); var position = json.GetProperty("position").GetInt32();
var color = json var color = json

View file

@ -58,11 +58,11 @@ namespace DiscordChatExporter.Core.Discord.Data
public static User Parse(JsonElement json) public static User Parse(JsonElement json)
{ {
var id = json.GetProperty("id").GetString().Pipe(Snowflake.Parse); var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse);
var isBot = json.GetPropertyOrNull("bot")?.GetBoolean() ?? false; var isBot = json.GetPropertyOrNull("bot")?.GetBoolean() ?? false;
var discriminator = json.GetProperty("discriminator").GetString().Pipe(int.Parse); var discriminator = json.GetProperty("discriminator").GetNonWhiteSpaceString().Pipe(int.Parse);
var name = json.GetProperty("username").GetString(); var name = json.GetProperty("username").GetNonWhiteSpaceString();
var avatarHash = json.GetProperty("avatar").GetString(); var avatarHash = json.GetPropertyOrNull("avatar")?.GetStringOrNull();
var avatarUrl = !string.IsNullOrWhiteSpace(avatarHash) var avatarUrl = !string.IsNullOrWhiteSpace(avatarHash)
? GetAvatarUrl(id, avatarHash) ? GetAvatarUrl(id, avatarHash)

View file

@ -130,7 +130,7 @@ namespace DiscordChatExporter.Core.Discord
var responseOrdered = response var responseOrdered = response
.EnumerateArray() .EnumerateArray()
.OrderBy(j => j.GetProperty("position").GetInt32()) .OrderBy(j => j.GetProperty("position").GetInt32())
.ThenBy(j => Snowflake.Parse(j.GetProperty("id").GetString())) .ThenBy(j => j.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse))
.ToArray(); .ToArray();
var categories = responseOrdered var categories = responseOrdered
@ -142,7 +142,7 @@ namespace DiscordChatExporter.Core.Discord
foreach (var channelJson in responseOrdered) foreach (var channelJson in responseOrdered)
{ {
var parentId = channelJson.GetPropertyOrNull("parent_id")?.GetString(); var parentId = channelJson.GetPropertyOrNull("parent_id")?.GetStringOrNull();
var category = !string.IsNullOrWhiteSpace(parentId) var category = !string.IsNullOrWhiteSpace(parentId)
? categories.GetValueOrDefault(parentId) ? categories.GetValueOrDefault(parentId)
@ -205,7 +205,7 @@ namespace DiscordChatExporter.Core.Discord
{ {
var response = await GetJsonResponseAsync($"channels/{channelId}", cancellationToken); var response = await GetJsonResponseAsync($"channels/{channelId}", cancellationToken);
var parentId = response.GetPropertyOrNull("parent_id")?.GetString().Pipe(Snowflake.Parse); var parentId = response.GetPropertyOrNull("parent_id")?.GetStringOrNull()?.Pipe(Snowflake.Parse);
var category = parentId is not null var category = parentId is not null
? await GetChannelCategoryAsync(parentId.Value, cancellationToken) ? await GetChannelCategoryAsync(parentId.Value, cancellationToken)

View file

@ -0,0 +1,20 @@
using System;
using System.Text.Json;
namespace DiscordChatExporter.Core.Utils.Extensions
{
public static class JsonExtensions
{
public static string GetNonWhiteSpaceString(this JsonElement json)
{
if (json.ValueKind != JsonValueKind.String)
throw new FormatException();
var value = json.GetString();
if (string.IsNullOrWhiteSpace(value))
throw new FormatException();
return value;
}
}
}

View file

@ -33,7 +33,7 @@ namespace DiscordChatExporter.Core.Utils
// on the very first request. // on the very first request.
if (i > 3) if (i > 3)
{ {
var retryAfterDelay = result.Result.Headers.RetryAfter.Delta; var retryAfterDelay = result.Result.Headers.RetryAfter?.Delta;
if (retryAfterDelay is not null) if (retryAfterDelay is not null)
return retryAfterDelay.Value + TimeSpan.FromSeconds(1); // margin just in case return retryAfterDelay.Value + TimeSpan.FromSeconds(1); // margin just in case
} }

View file

@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>$(TargetFramework)-windows</TargetFramework>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<AssemblyName>DiscordChatExporter</AssemblyName> <AssemblyName>DiscordChatExporter</AssemblyName>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
@ -34,7 +35,7 @@
<Target Name="Format XAML" AfterTargets="BeforeBuild"> <Target Name="Format XAML" AfterTargets="BeforeBuild">
<Exec Command="dotnet tool restore" /> <Exec Command="dotnet tool restore" />
<Exec Command="dotnet xstyler -r -d ." /> <Exec Command="dotnet xstyler -r -d $(MSBuildProjectDirectory)" />
</Target> </Target>
</Project> </Project>