From 2f817fc08e083f26f6ceb83272eaf1e70281c5a4 Mon Sep 17 00:00:00 2001 From: Eduardo Braga Date: Wed, 8 Nov 2023 10:36:32 -0300 Subject: [PATCH 01/11] Add Json source generators and mark the library as trimmable. Add .NET 8 to the list of targets. --- Mastonet.Entities/Enums/FilterContext.cs | 5 ++- Mastonet.Entities/Enums/NotificationType.cs | 8 ++-- Mastonet.Entities/JsonSourceGenerators.cs | 10 +++++ Mastonet.Entities/Mastonet.Entities.csproj | 8 ++-- Mastonet.Tests/Mastonet.Tests.csproj | 6 +-- Mastonet/BaseHttpClient.cs | 6 ++- Mastonet/Mastonet.csproj | 6 ++- Mastonet/TimelineStreaming.cs | 6 +-- Mastonet/TimelineWebSocketStreaming.cs | 11 ++++- Mastonet/TryDeserializeContext.cs | 47 +++++++++++++++++++++ 10 files changed, 93 insertions(+), 20 deletions(-) create mode 100644 Mastonet.Entities/JsonSourceGenerators.cs create mode 100644 Mastonet/TryDeserializeContext.cs diff --git a/Mastonet.Entities/Enums/FilterContext.cs b/Mastonet.Entities/Enums/FilterContext.cs index 428347d..cba7581 100644 --- a/Mastonet.Entities/Enums/FilterContext.cs +++ b/Mastonet.Entities/Enums/FilterContext.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Text.Json; +using Mastonet.Entities; namespace Mastonet; @@ -21,7 +22,7 @@ public class FilterContextConverter : JsonConverter public override FilterContext Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { FilterContext context = 0; - var contextStrings = JsonSerializer.Deserialize>(ref reader, options); + var contextStrings = JsonSerializer.Deserialize>(ref reader, EntitiesContext.Default.IEnumerableString); if (contextStrings != null) { foreach (var contextString in contextStrings) { @@ -53,7 +54,7 @@ public override void Write(Utf8JsonWriter writer, FilterContext value, JsonSeria if ((value & FilterContext.Notifications) == FilterContext.Notifications) contextStrings.Add("notifications"); if ((value & FilterContext.Public) == FilterContext.Public) contextStrings.Add("public"); if ((value & FilterContext.Thread) == FilterContext.Thread) contextStrings.Add("thread"); - JsonSerializer.Serialize(writer, contextStrings, options); + JsonSerializer.Serialize(writer, contextStrings, EntitiesContext.Default.ListString); } } diff --git a/Mastonet.Entities/Enums/NotificationType.cs b/Mastonet.Entities/Enums/NotificationType.cs index 78c38e1..081f646 100644 --- a/Mastonet.Entities/Enums/NotificationType.cs +++ b/Mastonet.Entities/Enums/NotificationType.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Text.Json; +using Mastonet.Entities; namespace Mastonet; @@ -22,7 +23,7 @@ public class NotificationTypeConverter : JsonConverter public override NotificationType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { NotificationType context = 0; - var contextStrings = JsonSerializer.Deserialize>(ref reader, options); + var contextStrings = JsonSerializer.Deserialize(ref reader, EntitiesContext.Default.IEnumerableString); if (contextStrings != null) { foreach (var contextString in contextStrings) @@ -59,6 +60,7 @@ public override void Write(Utf8JsonWriter writer, NotificationType value, JsonSe if ((value & NotificationType.Reblog) == NotificationType.Reblog) contextStrings.Add("reblog"); if ((value & NotificationType.Mention) == NotificationType.Mention) contextStrings.Add("mention"); if ((value & NotificationType.Poll) == NotificationType.Poll) contextStrings.Add("poll"); - JsonSerializer.Serialize(writer, contextStrings, options); + JsonSerializer.Serialize(writer, contextStrings, EntitiesContext.Default.ListString); } -} \ No newline at end of file +} + diff --git a/Mastonet.Entities/JsonSourceGenerators.cs b/Mastonet.Entities/JsonSourceGenerators.cs new file mode 100644 index 0000000..efc7824 --- /dev/null +++ b/Mastonet.Entities/JsonSourceGenerators.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Mastonet.Entities; + +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(List))] +internal partial class EntitiesContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Mastonet.Entities/Mastonet.Entities.csproj b/Mastonet.Entities/Mastonet.Entities.csproj index 82c3eb1..33644a5 100644 --- a/Mastonet.Entities/Mastonet.Entities.csproj +++ b/Mastonet.Entities/Mastonet.Entities.csproj @@ -1,7 +1,7 @@ - + - netstandard2.0;net6.0;net7.0 + netstandard2.0;net6.0;net7.0;net8.0 latest enable Mastonet.Entities @@ -19,10 +19,12 @@ false README.md Mastodon + true + true - + diff --git a/Mastonet.Tests/Mastonet.Tests.csproj b/Mastonet.Tests/Mastonet.Tests.csproj index 5edeab9..2515553 100644 --- a/Mastonet.Tests/Mastonet.Tests.csproj +++ b/Mastonet.Tests/Mastonet.Tests.csproj @@ -5,9 +5,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers diff --git a/Mastonet/BaseHttpClient.cs b/Mastonet/BaseHttpClient.cs index 3ddee68..ea253f2 100644 --- a/Mastonet/BaseHttpClient.cs +++ b/Mastonet/BaseHttpClient.cs @@ -307,16 +307,18 @@ private static T TryDeserialize(string json) if (json[0] == '{') { - var error = JsonSerializer.Deserialize(json); + var error = JsonSerializer.Deserialize(json, ErrorContext.Default.Error); if (error != null && !string.IsNullOrEmpty(error.Description)) { throw new ServerErrorException(error); } } - return JsonSerializer.Deserialize(json)!; + return JsonSerializer.Deserialize(json, TryDeserializeContextOptions)!; } + private static readonly JsonSerializerOptions TryDeserializeContextOptions = new() { TypeInfoResolver = TryDeserializeContext.Default }; + protected static string AddQueryStringParam(string queryParams, string queryStringParam, string? value) { // Empty parm? Exit diff --git a/Mastonet/Mastonet.csproj b/Mastonet/Mastonet.csproj index 164d54f..faa245a 100644 --- a/Mastonet/Mastonet.csproj +++ b/Mastonet/Mastonet.csproj @@ -1,7 +1,7 @@  - netstandard2.0;net6.0;net7.0 + netstandard2.0;net6.0;net7.0;net8.0 latest enable Mastonet @@ -19,10 +19,12 @@ false README.md Mastodon + true + true - + diff --git a/Mastonet/TimelineStreaming.cs b/Mastonet/TimelineStreaming.cs index bd33a2f..ed8e0b6 100644 --- a/Mastonet/TimelineStreaming.cs +++ b/Mastonet/TimelineStreaming.cs @@ -32,14 +32,14 @@ protected void SendEvent(string eventName, string data) switch (eventName) { case "update": - var status = JsonSerializer.Deserialize(data); + var status = JsonSerializer.Deserialize(data, TryDeserializeContext.Default.Status); if (status != null) { OnUpdate?.Invoke(this, new StreamUpdateEventArgs(status)); } break; case "notification": - var notification = JsonSerializer.Deserialize(data); + var notification = JsonSerializer.Deserialize(data, TryDeserializeContext.Default.Notification); if (notification != null) { OnNotification?.Invoke(this, new StreamNotificationEventArgs(notification)); @@ -55,7 +55,7 @@ protected void SendEvent(string eventName, string data) OnFiltersChanged?.Invoke(this, new StreamFiltersChangedEventArgs()); break; case "conversation": - var conversation = JsonSerializer.Deserialize(data); + var conversation = JsonSerializer.Deserialize(data, TryDeserializeContext.Default.Conversation); if (conversation != null) { OnConversation?.Invoke(this, new StreamConversationEvenTargs(conversation)); diff --git a/Mastonet/TimelineWebSocketStreaming.cs b/Mastonet/TimelineWebSocketStreaming.cs index 9a54ce8..2c5deb7 100644 --- a/Mastonet/TimelineWebSocketStreaming.cs +++ b/Mastonet/TimelineWebSocketStreaming.cs @@ -6,8 +6,10 @@ using System.Net.WebSockets; using System.Text; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; +using static Mastonet.TimelineWebSocketStreaming; namespace Mastonet; @@ -81,7 +83,7 @@ public override async Task Start() { var messageStr = Encoding.UTF8.GetString(ms.ToArray()); - var message = JsonSerializer.Deserialize(messageStr); + var message = JsonSerializer.Deserialize(messageStr, TimelineMessageContext.Default.TimelineMessage); if (message != null) { SendEvent(message.Event, message.Payload); @@ -96,7 +98,7 @@ public override async Task Start() this.Stop(); } - private class TimelineMessage + internal class TimelineMessage { public string Event { get; set; } = default!; @@ -115,3 +117,8 @@ public override void Stop() base.Stop(); } } + +[JsonSerializable(typeof(TimelineMessage))] +internal partial class TimelineMessageContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Mastonet/TryDeserializeContext.cs b/Mastonet/TryDeserializeContext.cs new file mode 100644 index 0000000..86e61fb --- /dev/null +++ b/Mastonet/TryDeserializeContext.cs @@ -0,0 +1,47 @@ +using Mastonet.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace Mastonet; + +[JsonSerializable(typeof(Account))] +[JsonSerializable(typeof(Card))] +[JsonSerializable(typeof(Context))] +[JsonSerializable(typeof(Conversation))] +[JsonSerializable(typeof(Filter))] +[JsonSerializable(typeof(IdentityProof))] +[JsonSerializable(typeof(Instance))] +[JsonSerializable(typeof(InstanceV2))] +[JsonSerializable(typeof(List))] +[JsonSerializable(typeof(List))] +[JsonSerializable(typeof(Marker))] +[JsonSerializable(typeof(MastodonList))] +[JsonSerializable(typeof(Notification))] +[JsonSerializable(typeof(Poll))] +[JsonSerializable(typeof(ScheduledStatus))] +[JsonSerializable(typeof(SearchResults))] +[JsonSerializable(typeof(Status))] +[JsonSerializable(typeof(Tag))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] +internal partial class TryDeserializeContext : JsonSerializerContext +{ +} + +[JsonSerializable(typeof(Error))] +internal partial class ErrorContext : JsonSerializerContext +{ +} \ No newline at end of file From 25323557ea084f51286c88c11bef132dbd05af7e Mon Sep 17 00:00:00 2001 From: Eduardo Braga Date: Wed, 8 Nov 2023 11:01:55 -0300 Subject: [PATCH 02/11] Add "Follow" scope to the GranularScopes enum --- Mastonet.Entities/Enums/Scope.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Mastonet.Entities/Enums/Scope.cs b/Mastonet.Entities/Enums/Scope.cs index 23322a6..3c9141c 100644 --- a/Mastonet.Entities/Enums/Scope.cs +++ b/Mastonet.Entities/Enums/Scope.cs @@ -34,6 +34,7 @@ public enum GranularScope Write__Reports, Write__Statuses, + Follow, Push, Admin__Read, From 0470af91c01ed5501b426ee53dede51adbe0bf1d Mon Sep 17 00:00:00 2001 From: Eduardo Braga Date: Sun, 12 Nov 2023 20:36:42 -0300 Subject: [PATCH 03/11] Updated Trending tags signature and added Trending statuses --- Mastonet/MastodonClient.cs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Mastonet/MastodonClient.cs b/Mastonet/MastodonClient.cs index f2e1224..72eec2b 100644 --- a/Mastonet/MastodonClient.cs +++ b/Mastonet/MastodonClient.cs @@ -74,7 +74,29 @@ public Task> GetInstanceActivity() /// public Task> GetTrendingTags() { - return Get>("/api/v1/trends"); + return Get>("/api/v1/trends/tags"); + } + + /// + /// Statuses that have been interacted with more than others. + /// + /// + /// + /// + public Task> GetTrendingStatuses(int? offset = null, int? limit = null) + { + var queryParams = ""; + + if(offset.HasValue) + { + queryParams = "?offset=" + offset.Value; + } + if(limit.HasValue) + { + queryParams += (queryParams != "" ? "&" : "?") + "limit=" + limit.Value; + } + + return GetMastodonList("/api/v1/trends/statuses" + queryParams); } /// @@ -348,7 +370,7 @@ public Task UploadMedia(MediaDefinition media, string? description = data.Add("focus", $"{focus.X},{focus.Y}"); } - return this.Post("/api/v1/media", data, list); + return this.Post("/api/v2/media", data, list); } /// From d831544e79752e8661b9e0d018afd5fd0d9fa1be Mon Sep 17 00:00:00 2001 From: Eduardo Braga Date: Mon, 13 Nov 2023 19:07:01 -0300 Subject: [PATCH 04/11] For some reason I had to add ToLower when converting Poll.Multiple to string. Sending as "False" wasn't working, but "false" is. --- Mastonet/MastodonClient.Status.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mastonet/MastodonClient.Status.cs b/Mastonet/MastodonClient.Status.cs index 32775c1..f181b8d 100644 --- a/Mastonet/MastodonClient.Status.cs +++ b/Mastonet/MastodonClient.Status.cs @@ -147,7 +147,7 @@ public Task PublishStatus(string status, Visibility? visibility = null, data.Add(new KeyValuePair("poll[expires_in]", poll.ExpiresIn.TotalSeconds.ToString())); if (poll.Multiple.HasValue) { - data.Add(new KeyValuePair("poll[multiple]", poll.Multiple.Value.ToString())); + data.Add(new KeyValuePair("poll[multiple]", poll.Multiple.Value.ToString().ToLower())); } if (poll.HideTotals.HasValue) From 476f588454462f43ffde0ede72b0b17e8a8a9e78 Mon Sep 17 00:00:00 2001 From: Eduardo Braga Date: Fri, 17 Nov 2023 00:33:28 -0300 Subject: [PATCH 05/11] Update nuget packages. --- Mastonet.Entities/Enums/FilterContext.cs | 7 +++---- Mastonet.Entities/Mastonet.Entities.csproj | 4 ++-- Mastonet/Mastonet.csproj | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Mastonet.Entities/Enums/FilterContext.cs b/Mastonet.Entities/Enums/FilterContext.cs index cba7581..02100dc 100644 --- a/Mastonet.Entities/Enums/FilterContext.cs +++ b/Mastonet.Entities/Enums/FilterContext.cs @@ -22,7 +22,7 @@ public class FilterContextConverter : JsonConverter public override FilterContext Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { FilterContext context = 0; - var contextStrings = JsonSerializer.Deserialize>(ref reader, EntitiesContext.Default.IEnumerableString); + var contextStrings = JsonSerializer.Deserialize(ref reader, EntitiesContext.Default.IEnumerableString); if (contextStrings != null) { foreach (var contextString in contextStrings) { @@ -55,6 +55,5 @@ public override void Write(Utf8JsonWriter writer, FilterContext value, JsonSeria if ((value & FilterContext.Public) == FilterContext.Public) contextStrings.Add("public"); if ((value & FilterContext.Thread) == FilterContext.Thread) contextStrings.Add("thread"); JsonSerializer.Serialize(writer, contextStrings, EntitiesContext.Default.ListString); - } - -} + } +} \ No newline at end of file diff --git a/Mastonet.Entities/Mastonet.Entities.csproj b/Mastonet.Entities/Mastonet.Entities.csproj index 33644a5..969f815 100644 --- a/Mastonet.Entities/Mastonet.Entities.csproj +++ b/Mastonet.Entities/Mastonet.Entities.csproj @@ -24,11 +24,11 @@ - + - + diff --git a/Mastonet/Mastonet.csproj b/Mastonet/Mastonet.csproj index faa245a..969fa62 100644 --- a/Mastonet/Mastonet.csproj +++ b/Mastonet/Mastonet.csproj @@ -24,11 +24,11 @@ - + - + From c4cf12177cf76dcc483e3e000fbd8b668c7255ad Mon Sep 17 00:00:00 2001 From: Eduardo Braga Date: Mon, 20 Nov 2023 10:26:32 -0300 Subject: [PATCH 06/11] Added missing types to serialization context --- Mastonet/TryDeserializeContext.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Mastonet/TryDeserializeContext.cs b/Mastonet/TryDeserializeContext.cs index 86e61fb..e1ec053 100644 --- a/Mastonet/TryDeserializeContext.cs +++ b/Mastonet/TryDeserializeContext.cs @@ -8,6 +8,10 @@ namespace Mastonet; + +[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] +[JsonSerializable(typeof(MastodonList))] +[JsonSerializable(typeof(Status))] [JsonSerializable(typeof(Account))] [JsonSerializable(typeof(Card))] [JsonSerializable(typeof(Context))] @@ -19,13 +23,13 @@ namespace Mastonet; [JsonSerializable(typeof(List))] [JsonSerializable(typeof(List))] [JsonSerializable(typeof(Marker))] -[JsonSerializable(typeof(MastodonList))] [JsonSerializable(typeof(Notification))] [JsonSerializable(typeof(Poll))] [JsonSerializable(typeof(ScheduledStatus))] [JsonSerializable(typeof(SearchResults))] -[JsonSerializable(typeof(Status))] [JsonSerializable(typeof(Tag))] +[JsonSerializable(typeof(AppRegistration))] +[JsonSerializable(typeof(Auth))] [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IEnumerable))] @@ -41,7 +45,7 @@ internal partial class TryDeserializeContext : JsonSerializerContext { } -[JsonSerializable(typeof(Error))] +[JsonSerializable(typeof(Error), GenerationMode = JsonSourceGenerationMode.Metadata)] internal partial class ErrorContext : JsonSerializerContext { } \ No newline at end of file From 3c5f17588e354919a6ddfcb57afaca539670d781 Mon Sep 17 00:00:00 2001 From: Eduardo Braga Date: Fri, 24 Nov 2023 19:38:49 -0300 Subject: [PATCH 07/11] Added guards so it only uses source generators if .NET 6 and up --- Mastonet.Entities/Enums/FilterContext.cs | 15 ++++++++++++--- Mastonet.Entities/Enums/NotificationType.cs | 8 ++++++++ Mastonet/BaseHttpClient.cs | 14 +++++++++++--- Mastonet/MastodonClient.Status.cs | 2 +- Mastonet/MastodonClient.cs | 2 +- Mastonet/TimelineStreaming.cs | 12 ++++++++++++ Mastonet/TimelineWebSocketStreaming.cs | 6 +++++- Mastonet/TryDeserializeContext.cs | 7 +++---- 8 files changed, 53 insertions(+), 13 deletions(-) diff --git a/Mastonet.Entities/Enums/FilterContext.cs b/Mastonet.Entities/Enums/FilterContext.cs index 02100dc..df66d12 100644 --- a/Mastonet.Entities/Enums/FilterContext.cs +++ b/Mastonet.Entities/Enums/FilterContext.cs @@ -22,8 +22,13 @@ public class FilterContextConverter : JsonConverter public override FilterContext Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { FilterContext context = 0; +#if NET6_0_OR_GREATER var contextStrings = JsonSerializer.Deserialize(ref reader, EntitiesContext.Default.IEnumerableString); - if (contextStrings != null) { +#else +var contextStrings = JsonSerializer.Deserialize>(ref reader, options); +#endif + if (contextStrings != null) + { foreach (var contextString in contextStrings) { switch (contextString) @@ -46,7 +51,7 @@ public override FilterContext Read(ref Utf8JsonReader reader, Type typeToConvert return context; } - + public override void Write(Utf8JsonWriter writer, FilterContext value, JsonSerializerOptions options) { var contextStrings = new List(); @@ -54,6 +59,10 @@ public override void Write(Utf8JsonWriter writer, FilterContext value, JsonSeria if ((value & FilterContext.Notifications) == FilterContext.Notifications) contextStrings.Add("notifications"); if ((value & FilterContext.Public) == FilterContext.Public) contextStrings.Add("public"); if ((value & FilterContext.Thread) == FilterContext.Thread) contextStrings.Add("thread"); +#if NET6_0_OR_GREATER JsonSerializer.Serialize(writer, contextStrings, EntitiesContext.Default.ListString); - } +#else +JsonSerializer.Serialize(writer, contextStrings, options); +#endif + } } \ No newline at end of file diff --git a/Mastonet.Entities/Enums/NotificationType.cs b/Mastonet.Entities/Enums/NotificationType.cs index 081f646..2ab9a4a 100644 --- a/Mastonet.Entities/Enums/NotificationType.cs +++ b/Mastonet.Entities/Enums/NotificationType.cs @@ -23,7 +23,11 @@ public class NotificationTypeConverter : JsonConverter public override NotificationType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { NotificationType context = 0; +#if NET6_0_OR_GREATER var contextStrings = JsonSerializer.Deserialize(ref reader, EntitiesContext.Default.IEnumerableString); +#else +var contextStrings = JsonSerializer.Deserialize>(ref reader, options); +#endif if (contextStrings != null) { foreach (var contextString in contextStrings) @@ -60,7 +64,11 @@ public override void Write(Utf8JsonWriter writer, NotificationType value, JsonSe if ((value & NotificationType.Reblog) == NotificationType.Reblog) contextStrings.Add("reblog"); if ((value & NotificationType.Mention) == NotificationType.Mention) contextStrings.Add("mention"); if ((value & NotificationType.Poll) == NotificationType.Poll) contextStrings.Add("poll"); +#if NET6_0_OR_GREATER JsonSerializer.Serialize(writer, contextStrings, EntitiesContext.Default.ListString); +#else +JsonSerializer.Serialize(writer, contextStrings, options); +#endif } } diff --git a/Mastonet/BaseHttpClient.cs b/Mastonet/BaseHttpClient.cs index ea253f2..554b7c6 100644 --- a/Mastonet/BaseHttpClient.cs +++ b/Mastonet/BaseHttpClient.cs @@ -306,15 +306,23 @@ private static T TryDeserialize(string json) { if (json[0] == '{') { - +#if NET6_0_OR_GREATER var error = JsonSerializer.Deserialize(json, ErrorContext.Default.Error); +#else +var error = JsonSerializer.Deserialize(json); +#endif if (error != null && !string.IsNullOrEmpty(error.Description)) { throw new ServerErrorException(error); } } - return JsonSerializer.Deserialize(json, TryDeserializeContextOptions)!; +#if NET6_0_OR_GREATER + return JsonSerializer.Deserialize(json, TryDeserializeContextOptions); +#else + return JsonSerializer.Deserialize(json); + +#endif } private static readonly JsonSerializerOptions TryDeserializeContextOptions = new() { TypeInfoResolver = TryDeserializeContext.Default }; @@ -338,7 +346,7 @@ protected static string GetQueryStringConcatChar(string queryParams) return !string.IsNullOrEmpty(queryParams) ? "&" : "?"; } - #endregion +#endregion } diff --git a/Mastonet/MastodonClient.Status.cs b/Mastonet/MastodonClient.Status.cs index f181b8d..fca56f8 100644 --- a/Mastonet/MastodonClient.Status.cs +++ b/Mastonet/MastodonClient.Status.cs @@ -147,7 +147,7 @@ public Task PublishStatus(string status, Visibility? visibility = null, data.Add(new KeyValuePair("poll[expires_in]", poll.ExpiresIn.TotalSeconds.ToString())); if (poll.Multiple.HasValue) { - data.Add(new KeyValuePair("poll[multiple]", poll.Multiple.Value.ToString().ToLower())); + data.Add(new KeyValuePair("poll[multiple]", poll.Multiple.Value.ToString().ToLowerInvariant())); } if (poll.HideTotals.HasValue) diff --git a/Mastonet/MastodonClient.cs b/Mastonet/MastodonClient.cs index 72eec2b..cea31b1 100644 --- a/Mastonet/MastodonClient.cs +++ b/Mastonet/MastodonClient.cs @@ -524,7 +524,7 @@ public Task Report(string accountId, IEnumerable? statusIds = nu { var data = new List>() { - new KeyValuePair("account_id", accountId.ToString()), + new KeyValuePair("account_id", accountId), }; if (statusIds != null) { diff --git a/Mastonet/TimelineStreaming.cs b/Mastonet/TimelineStreaming.cs index ed8e0b6..b08e3ce 100644 --- a/Mastonet/TimelineStreaming.cs +++ b/Mastonet/TimelineStreaming.cs @@ -32,14 +32,22 @@ protected void SendEvent(string eventName, string data) switch (eventName) { case "update": +#if NET6_0_OR_GREATER var status = JsonSerializer.Deserialize(data, TryDeserializeContext.Default.Status); +#else +var status = JsonSerializer.Deserialize(data); +#endif if (status != null) { OnUpdate?.Invoke(this, new StreamUpdateEventArgs(status)); } break; case "notification": +#if NET6_0_OR_GREATER var notification = JsonSerializer.Deserialize(data, TryDeserializeContext.Default.Notification); +#else +var notification = JsonSerializer.Deserialize(data); +#endif if (notification != null) { OnNotification?.Invoke(this, new StreamNotificationEventArgs(notification)); @@ -55,7 +63,11 @@ protected void SendEvent(string eventName, string data) OnFiltersChanged?.Invoke(this, new StreamFiltersChangedEventArgs()); break; case "conversation": +#if NET6_0_OR_GREATER var conversation = JsonSerializer.Deserialize(data, TryDeserializeContext.Default.Conversation); +#else +var conversation = JsonSerializer.Deserialize(data); +#endif if (conversation != null) { OnConversation?.Invoke(this, new StreamConversationEvenTargs(conversation)); diff --git a/Mastonet/TimelineWebSocketStreaming.cs b/Mastonet/TimelineWebSocketStreaming.cs index 2c5deb7..5ff43ee 100644 --- a/Mastonet/TimelineWebSocketStreaming.cs +++ b/Mastonet/TimelineWebSocketStreaming.cs @@ -83,7 +83,11 @@ public override async Task Start() { var messageStr = Encoding.UTF8.GetString(ms.ToArray()); - var message = JsonSerializer.Deserialize(messageStr, TimelineMessageContext.Default.TimelineMessage); +#if NET6_0_OR_GREATER + var message = JsonSerializer.Deserialize(messageStr, TimelineMessageContext.Default.TimelineMessage); +#else +var message = JsonSerializer.Deserialize(messageStr); +#endif if (message != null) { SendEvent(message.Event, message.Payload); diff --git a/Mastonet/TryDeserializeContext.cs b/Mastonet/TryDeserializeContext.cs index e1ec053..ed06196 100644 --- a/Mastonet/TryDeserializeContext.cs +++ b/Mastonet/TryDeserializeContext.cs @@ -10,11 +10,12 @@ namespace Mastonet; [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] -[JsonSerializable(typeof(MastodonList))] [JsonSerializable(typeof(Status))] -[JsonSerializable(typeof(Account))] +[JsonSerializable(typeof(MastodonList))] [JsonSerializable(typeof(Card))] [JsonSerializable(typeof(Context))] +[JsonSerializable(typeof(Poll))] +[JsonSerializable(typeof(Account))] [JsonSerializable(typeof(Conversation))] [JsonSerializable(typeof(Filter))] [JsonSerializable(typeof(IdentityProof))] @@ -24,10 +25,8 @@ namespace Mastonet; [JsonSerializable(typeof(List))] [JsonSerializable(typeof(Marker))] [JsonSerializable(typeof(Notification))] -[JsonSerializable(typeof(Poll))] [JsonSerializable(typeof(ScheduledStatus))] [JsonSerializable(typeof(SearchResults))] -[JsonSerializable(typeof(Tag))] [JsonSerializable(typeof(AppRegistration))] [JsonSerializable(typeof(Auth))] [JsonSerializable(typeof(IEnumerable))] From abdd2ac17ce7fc9456b4e7db2c6feb00229fc7a5 Mon Sep 17 00:00:00 2001 From: Eduardo Braga Date: Wed, 29 Nov 2023 11:32:57 -0300 Subject: [PATCH 08/11] Added some missing types and reorganized the source generator's attributes. Despite the code repetition, I thought it was better to just have one if/else directive in the TryDeserialize method. --- Mastonet/BaseHttpClient.cs | 20 +++++++++++++------- Mastonet/TryDeserializeContext.cs | 17 +++++++++++++++-- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/Mastonet/BaseHttpClient.cs b/Mastonet/BaseHttpClient.cs index 554b7c6..963f1f8 100644 --- a/Mastonet/BaseHttpClient.cs +++ b/Mastonet/BaseHttpClient.cs @@ -304,22 +304,28 @@ protected async Task PatchMedia(string route, IEnumerable(string json) { +#if NET6_0_OR_GREATER if (json[0] == '{') { -#if NET6_0_OR_GREATER var error = JsonSerializer.Deserialize(json, ErrorContext.Default.Error); -#else -var error = JsonSerializer.Deserialize(json); -#endif + if (error != null && !string.IsNullOrEmpty(error.Description)) { throw new ServerErrorException(error); } } - -#if NET6_0_OR_GREATER return JsonSerializer.Deserialize(json, TryDeserializeContextOptions); #else +if (json[0] == '{') + { + var error = JsonSerializer.Deserialize(json); + + if (error != null && !string.IsNullOrEmpty(error.Description)) + { + throw new ServerErrorException(error); + } + } + return JsonSerializer.Deserialize(json); #endif @@ -346,7 +352,7 @@ protected static string GetQueryStringConcatChar(string queryParams) return !string.IsNullOrEmpty(queryParams) ? "&" : "?"; } -#endregion + #endregion } diff --git a/Mastonet/TryDeserializeContext.cs b/Mastonet/TryDeserializeContext.cs index ed06196..a38251b 100644 --- a/Mastonet/TryDeserializeContext.cs +++ b/Mastonet/TryDeserializeContext.cs @@ -11,10 +11,11 @@ namespace Mastonet; [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(Status))] -[JsonSerializable(typeof(MastodonList))] +[JsonSerializable(typeof(Attachment))] [JsonSerializable(typeof(Card))] -[JsonSerializable(typeof(Context))] [JsonSerializable(typeof(Poll))] +[JsonSerializable(typeof(Context))] +[JsonSerializable(typeof(MastodonList))] [JsonSerializable(typeof(Account))] [JsonSerializable(typeof(Conversation))] [JsonSerializable(typeof(Filter))] @@ -29,6 +30,17 @@ namespace Mastonet; [JsonSerializable(typeof(SearchResults))] [JsonSerializable(typeof(AppRegistration))] [JsonSerializable(typeof(Auth))] +[JsonSerializable(typeof(Tag))] +[JsonSerializable(typeof(Report))] +[JsonSerializable(typeof(FeaturedTag))] +[JsonSerializable(typeof(Relationship))] +[JsonSerializable(typeof(MastodonList))] +[JsonSerializable(typeof(MastodonList))] +[JsonSerializable(typeof(MastodonList))] +[JsonSerializable(typeof(MastodonList))] +[JsonSerializable(typeof(MastodonList))] +[JsonSerializable(typeof(MastodonList))] +[JsonSerializable(typeof(MastodonList))] [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IEnumerable))] @@ -40,6 +52,7 @@ namespace Mastonet; [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IdentityProof))] internal partial class TryDeserializeContext : JsonSerializerContext { } From eb2adf6578cb2dc4c6bb2b42271550a3192126a9 Mon Sep 17 00:00:00 2001 From: Eduardo Braga Date: Sat, 2 Dec 2023 11:18:40 -0300 Subject: [PATCH 09/11] Fixed the remaining trim warning. Everything seems to be working fine for now. --- Mastonet/BaseHttpClient.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Mastonet/BaseHttpClient.cs b/Mastonet/BaseHttpClient.cs index 963f1f8..b79799a 100644 --- a/Mastonet/BaseHttpClient.cs +++ b/Mastonet/BaseHttpClient.cs @@ -305,6 +305,7 @@ protected async Task PatchMedia(string route, IEnumerable(string json) { #if NET6_0_OR_GREATER + if (json[0] == '{') { var error = JsonSerializer.Deserialize(json, ErrorContext.Default.Error); @@ -314,8 +315,10 @@ private static T TryDeserialize(string json) throw new ServerErrorException(error); } } - return JsonSerializer.Deserialize(json, TryDeserializeContextOptions); + + return (T?)JsonSerializer.Deserialize(json, typeof(T), TryDeserializeContext.Default)!; #else + if (json[0] == '{') { var error = JsonSerializer.Deserialize(json); @@ -326,13 +329,11 @@ private static T TryDeserialize(string json) } } - return JsonSerializer.Deserialize(json); + return JsonSerializer.Deserialize(json)!; #endif } - private static readonly JsonSerializerOptions TryDeserializeContextOptions = new() { TypeInfoResolver = TryDeserializeContext.Default }; - protected static string AddQueryStringParam(string queryParams, string queryStringParam, string? value) { // Empty parm? Exit From b7ac526fce599e35276fbe05409048fb8c8f18c8 Mon Sep 17 00:00:00 2001 From: Eduardo Braga Date: Fri, 15 Dec 2023 11:28:37 -0300 Subject: [PATCH 10/11] Reorder TryDeserializeContext attributes --- Mastonet/TryDeserializeContext.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Mastonet/TryDeserializeContext.cs b/Mastonet/TryDeserializeContext.cs index a38251b..ba20324 100644 --- a/Mastonet/TryDeserializeContext.cs +++ b/Mastonet/TryDeserializeContext.cs @@ -11,18 +11,21 @@ namespace Mastonet; [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(Status))] +[JsonSerializable(typeof(MastodonList))] +[JsonSerializable(typeof(Context))] +[JsonSerializable(typeof(List))] [JsonSerializable(typeof(Attachment))] [JsonSerializable(typeof(Card))] [JsonSerializable(typeof(Poll))] -[JsonSerializable(typeof(Context))] -[JsonSerializable(typeof(MastodonList))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(Account))] +[JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(Conversation))] [JsonSerializable(typeof(Filter))] [JsonSerializable(typeof(IdentityProof))] -[JsonSerializable(typeof(Instance))] [JsonSerializable(typeof(InstanceV2))] -[JsonSerializable(typeof(List))] +[JsonSerializable(typeof(Instance))] [JsonSerializable(typeof(List))] [JsonSerializable(typeof(Marker))] [JsonSerializable(typeof(Notification))] @@ -41,17 +44,14 @@ namespace Mastonet; [JsonSerializable(typeof(MastodonList))] [JsonSerializable(typeof(MastodonList))] [JsonSerializable(typeof(MastodonList))] +[JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IEnumerable))] -[JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IEnumerable))] -[JsonSerializable(typeof(IEnumerable))] -[JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IEnumerable))] -[JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(IdentityProof))] internal partial class TryDeserializeContext : JsonSerializerContext { From 1d3dd83dc0ab62d80d40ee755bf65cacafaab94d Mon Sep 17 00:00:00 2001 From: Eduardo Braga Date: Fri, 15 Dec 2023 11:29:50 -0300 Subject: [PATCH 11/11] Add ToLowerInvairant() to HideTotals --- Mastonet/MastodonClient.Status.cs | 2 +- Mastonet/TimelineWebSocketStreaming.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Mastonet/MastodonClient.Status.cs b/Mastonet/MastodonClient.Status.cs index fca56f8..6ca560f 100644 --- a/Mastonet/MastodonClient.Status.cs +++ b/Mastonet/MastodonClient.Status.cs @@ -152,7 +152,7 @@ public Task PublishStatus(string status, Visibility? visibility = null, if (poll.HideTotals.HasValue) { - data.Add(new KeyValuePair("poll[hide_totals]", poll.HideTotals.Value.ToString())); + data.Add(new KeyValuePair("poll[hide_totals]", poll.HideTotals.Value.ToString().ToLowerInvariant())); } } diff --git a/Mastonet/TimelineWebSocketStreaming.cs b/Mastonet/TimelineWebSocketStreaming.cs index 5ff43ee..9b41630 100644 --- a/Mastonet/TimelineWebSocketStreaming.cs +++ b/Mastonet/TimelineWebSocketStreaming.cs @@ -122,7 +122,7 @@ public override void Stop() } } -[JsonSerializable(typeof(TimelineMessage))] +[JsonSerializable(typeof(TimelineMessage), GenerationMode = JsonSourceGenerationMode.Metadata)] internal partial class TimelineMessageContext : JsonSerializerContext { } \ No newline at end of file