diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NoteRenderer.cs b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NoteRenderer.cs index 6ce1f067..d70ae027 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NoteRenderer.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NoteRenderer.cs @@ -103,8 +103,8 @@ public class NoteRenderer( Renote = renote, Quote = quote, ContentType = "text/x.misskeymarkdown", - CreatedAt = note.CreatedAt.ToStringMastodon(), - EditedAt = note.UpdatedAt?.ToStringMastodon(), + CreatedAt = note.CreatedAt.ToStringIso8601Like(), + EditedAt = note.UpdatedAt?.ToStringIso8601Like(), RepliesCount = note.RepliesCount, RenoteCount = note.RenoteCount, FavoriteCount = likeCount, diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NotificationRenderer.cs b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NotificationRenderer.cs index 3a47a0f7..024a3774 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NotificationRenderer.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NotificationRenderer.cs @@ -37,7 +37,7 @@ public class NotificationRenderer(NoteRenderer noteRenderer, UserRenderer userRe Type = NotificationEntity.EncodeType(notification.Type), Note = note, Notifier = notifier, - CreatedAt = notification.CreatedAt.ToStringMastodon() + CreatedAt = notification.CreatedAt.ToStringIso8601Like() }; return res; diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/UserRenderer.cs b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/UserRenderer.cs index 9b024caf..4817ceb6 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/UserRenderer.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/UserRenderer.cs @@ -26,7 +26,7 @@ public class UserRenderer(IOptions config, MfmConverter Acct = acct, FullyQualifiedName = $"{user.Username}@{user.Host ?? config.Value.AccountDomain}", IsLocked = user.IsLocked, - CreatedAt = user.CreatedAt.ToStringMastodon(), + CreatedAt = user.CreatedAt.ToStringIso8601Like(), FollowersCount = user.FollowersCount, FollowingCount = user.FollowingCount, StatusesCount = user.NotesCount, diff --git a/Iceshrimp.Backend/Core/Configuration/Constants.cs b/Iceshrimp.Backend/Core/Configuration/Constants.cs index dac02934..860e3ced 100644 --- a/Iceshrimp.Backend/Core/Configuration/Constants.cs +++ b/Iceshrimp.Backend/Core/Configuration/Constants.cs @@ -5,6 +5,7 @@ public static class Constants public const string ActivityStreamsNs = "https://www.w3.org/ns/activitystreams"; public const string W3IdSecurityNs = "https://w3id.org/security"; public const string PurlDcNs = "http://purl.org/dc/terms"; + public const string XsdNs = "http://www.w3.org/2001/XMLSchema"; public static readonly string[] SystemUsers = ["instance.actor", "relay.actor"]; public static readonly string[] BrowserSafeMimeTypes = diff --git a/Iceshrimp.Backend/Core/Extensions/DateTimeExtensions.cs b/Iceshrimp.Backend/Core/Extensions/DateTimeExtensions.cs index d4a466d1..31849979 100644 --- a/Iceshrimp.Backend/Core/Extensions/DateTimeExtensions.cs +++ b/Iceshrimp.Backend/Core/Extensions/DateTimeExtensions.cs @@ -2,7 +2,7 @@ namespace Iceshrimp.Backend.Core.Extensions; public static class DateTimeExtensions { - public static string ToStringMastodon(this DateTime dateTime) + public static string ToStringIso8601Like(this DateTime dateTime) { return dateTime.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffK"); } diff --git a/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASCollection.cs b/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASCollection.cs index b0debf3d..fb327b1d 100644 --- a/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASCollection.cs +++ b/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASCollection.cs @@ -20,7 +20,7 @@ public class ASCollection() : ASObjectBase where T : ASObject [J($"{Constants.ActivityStreamsNs}#totalItems")] [JC(typeof(VC))] - public long? TotalItems { get; set; } + public uint? TotalItems { get; set; } } public sealed class ASCollectionConverter : ASSerializer.ListSingleObjectConverter>; diff --git a/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/LDValueObject.cs b/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/LDValueObject.cs index 22cbb5ea..2c6c3636 100644 --- a/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/LDValueObject.cs +++ b/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/LDValueObject.cs @@ -1,3 +1,5 @@ +using Iceshrimp.Backend.Core.Configuration; +using Iceshrimp.Backend.Core.Extensions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using J = Newtonsoft.Json.JsonPropertyAttribute; @@ -12,7 +14,7 @@ public class LDValueObject public class ValueObjectConverter : JsonConverter { - public override bool CanWrite => false; + public override bool CanWrite => true; public override bool CanConvert(Type objectType) { @@ -43,6 +45,28 @@ public class ValueObjectConverter : JsonConverter public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { - throw new NotImplementedException(); + writer.WriteStartObject(); + + switch (value) + { + case DateTime dt: + writer.WritePropertyName("@type"); + writer.WriteValue($"{Constants.XsdNs}#dateTime"); + writer.WritePropertyName("@value"); + writer.WriteValue(dt.ToStringIso8601Like()); + break; + case uint ui: + writer.WritePropertyName("@type"); + writer.WriteValue($"{Constants.XsdNs}#nonNegativeInteger"); + writer.WritePropertyName("@value"); + writer.WriteValue(ui); + break; + default: + writer.WritePropertyName("@value"); + writer.WriteValue(value); + break; + } + + writer.WriteEndObject(); } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Core/Services/QueueService.cs b/Iceshrimp.Backend/Core/Services/QueueService.cs index e5091fe0..511fa18f 100644 --- a/Iceshrimp.Backend/Core/Services/QueueService.cs +++ b/Iceshrimp.Backend/Core/Services/QueueService.cs @@ -219,7 +219,7 @@ public class JobQueue( else { logger.LogTrace("Job in queue {queue} completed after {duration} ms, has been queued since {time}", - name, job.Duration, job.QueuedAt.ToStringMastodon()); + name, job.Duration, job.QueuedAt.ToStringIso8601Like()); } } @@ -236,8 +236,8 @@ public class JobQueue( job.DelayedUntil ??= DateTime.Now; var logger = scope.ServiceProvider.GetRequiredService>(); logger.LogTrace("Job in queue {queue} was delayed to {time} after {duration} ms, has been queued since {time}", - name, job.DelayedUntil.Value.ToStringMastodon(), job.Duration, - job.QueuedAt.ToStringMastodon()); + name, job.DelayedUntil.Value.ToStringIso8601Like(), job.Duration, + job.QueuedAt.ToStringIso8601Like()); var timestamp = (long)job.DelayedUntil.Value.Subtract(DateTime.UnixEpoch).TotalSeconds; await _redisDb.SortedSetAddAsync(targetQueue, RedisValue.Unbox(RedisHelpers.Serialize(job)), timestamp);