[backend/federation] Handle user profile fields (ISH-34)

This commit is contained in:
Laura Hausmann 2024-02-25 00:55:35 +01:00
parent 90eb93cfb2
commit 2f3ca1e477
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
8 changed files with 51 additions and 9 deletions

View file

@ -22,6 +22,16 @@ public class UserRenderer(IOptions<Config.InstanceSection> config, MfmConverter
acct += $"@{user.Host}";
var profileEmoji = emoji?.Where(p => user.Emojis.Contains(p.Id)).ToList() ?? await GetEmoji([user]);
var fields = profile?.Fields
.Select(p => new Field
{
Name = p.Name,
Value = p.Value,
VerifiedAt = p.IsVerified.HasValue && p.IsVerified.Value
? DateTime.Now.ToStringIso8601Like()
: null
})
.ToList();
var res = new AccountEntity
{
@ -44,7 +54,7 @@ public class UserRenderer(IOptions<Config.InstanceSection> config, MfmConverter
MovedToAccount = null, //TODO
IsBot = user.IsBot,
IsDiscoverable = user.IsExplorable,
Fields = [], //TODO
Fields = fields ?? [],
Emoji = profileEmoji
};

View file

@ -23,7 +23,7 @@ public class AccountEntity : IEntity
[J("moved")] public required AccountEntity? MovedToAccount { get; set; }
[J("bot")] public required bool IsBot { get; set; }
[J("discoverable")] public required bool IsDiscoverable { get; set; }
[J("fields")] public required Field[] Fields { get; set; }
[J("fields")] public required List<Field> Fields { get; set; }
[J("source")] public AccountSource? Source { get; set; }
[J("emojis")] public required List<EmojiEntity> Emoji { get; set; }
[J("id")] public required string Id { get; set; }

View file

@ -6,6 +6,7 @@ public static class Constants
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 const string SchemaNs = "http://schema.org";
public const string MastodonNs = "http://joinmastodon.org/ns";
public static readonly string[] SystemUsers = ["instance.actor", "relay.actor"];

View file

@ -73,7 +73,6 @@ public class NoteRenderer(IOptions<Config.InstanceSection> config, MfmConverter
.Where(p => note.FileIds.Contains(p.Id) && p.UserHost == null)
.Select(p => new ASDocument
{
Type = $"{Constants.ActivityStreamsNs}#Document",
Sensitive = p.IsSensitive,
Url = new ASObjectBase(p.WebpublicUrl ?? p.Url),
MediaType = p.Type,

View file

@ -121,6 +121,10 @@ public class ASActor : ASObject
[JC(typeof(ASTagConverter))]
public List<ASTag>? Tags { get; set; }
[J($"{Constants.ActivityStreamsNs}#attachment")]
[JC(typeof(ASAttachmentConverter))]
public List<ASAttachment>? Attachments { get; set; }
public bool IsBot => Type == $"{Constants.ActivityStreamsNs}#Service";
public void Normalize(string uri, string acct)

View file

@ -15,6 +15,8 @@ public class ASAttachment : ASObjectBase
public class ASDocument : ASAttachment
{
public ASDocument() => Type = $"{Constants.ActivityStreamsNs}#Document";
[J($"{Constants.ActivityStreamsNs}#url")]
[JC(typeof(ASObjectBaseConverter))]
public ASObjectBase? Url { get; set; }
@ -32,6 +34,17 @@ public class ASDocument : ASAttachment
public string? Description { get; set; }
}
public class ASField : ASAttachment
{
public ASField() => Type = $"{Constants.SchemaNs}#PropertyValue";
[J($"{Constants.ActivityStreamsNs}#name")] [JC(typeof(ValueObjectConverter))]
public string? Name;
[J($"{Constants.SchemaNs}#value")] [JC(typeof(ValueObjectConverter))]
public string? Value;
}
public sealed class ASAttachmentConverter : JsonConverter
{
public override bool CanWrite => false;
@ -74,9 +87,12 @@ public sealed class ASAttachmentConverter : JsonConverter
{
var attachment = obj.ToObject<ASAttachment?>();
return attachment?.Type == $"{Constants.ActivityStreamsNs}#Document"
? obj.ToObject<ASDocument?>()
: attachment;
return attachment?.Type switch
{
$"{Constants.ActivityStreamsNs}#Document" => obj.ToObject<ASDocument?>(),
$"{Constants.SchemaNs}#PropertyValue" => obj.ToObject<ASField?>(),
_ => attachment
};
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)

View file

@ -583,6 +583,7 @@ public class NoteService(
if (attachments is not { Count: > 0 }) return [];
var result = await attachments
.OfType<ASDocument>()
.Take(10)
.Select(p => driveSvc.StoreFile(p.Url?.Id, user, p.Sensitive ?? sensitive, p.Description,
p.MediaType))
.AwaitAllNoConcurrencyAsync();

View file

@ -101,6 +101,11 @@ public class UserService(
.Where(p => p != null)
.Cast<string>()
.ToList();
var fields = actor.Attachments?
.OfType<ASField>()
.Where(p => p is { Name: not null, Value: not null })
.Select(p => new UserProfile.Field { Name = p.Name!, Value = p.Value! })
.ToArray();
user = new User
{
@ -134,7 +139,7 @@ public class UserService(
Description = actor.MkSummary ?? await mfmConverter.FromHtmlAsync(actor.Summary),
//Birthday = TODO,
//Location = TODO,
//Fields = TODO,
Fields = fields ?? [],
UserHost = user.Host,
Url = actor.Url?.Link
};
@ -226,6 +231,12 @@ public class UserService(
.Cast<string>()
.ToList();
var fields = actor.Attachments?
.OfType<ASField>()
.Where(p => p is { Name: not null, Value: not null })
.Select(p => new UserProfile.Field { Name = p.Name!, Value = p.Value! })
.ToArray();
user.Emojis = emoji.Select(p => p.Id).ToList();
user.Tags = tags ?? [];
//TODO: FollowersCount
@ -238,7 +249,7 @@ public class UserService(
user.UserProfile.Description = actor.MkSummary ?? await mfmConverter.FromHtmlAsync(actor.Summary);
//user.UserProfile.Birthday = TODO;
//user.UserProfile.Location = TODO;
//user.UserProfile.Fields = TODO;
user.UserProfile.Fields = fields ?? [];
user.UserProfile.UserHost = user.Host;
user.UserProfile.Url = actor.Url?.Link;