608 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			608 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System.ComponentModel.DataAnnotations;
 | 
						|
using System.ComponentModel.DataAnnotations.Schema;
 | 
						|
using System.Text.Json.Serialization;
 | 
						|
using DysonNetwork.Shared.Proto;
 | 
						|
using Google.Protobuf.WellKnownTypes;
 | 
						|
using NodaTime;
 | 
						|
 | 
						|
namespace DysonNetwork.Shared.Models;
 | 
						|
 | 
						|
public enum PostType
 | 
						|
{
 | 
						|
    Moment,
 | 
						|
    Article,
 | 
						|
}
 | 
						|
 | 
						|
public enum PostVisibility
 | 
						|
{
 | 
						|
    Public,
 | 
						|
    Friends,
 | 
						|
    Unlisted,
 | 
						|
    Private,
 | 
						|
}
 | 
						|
 | 
						|
public enum PostPinMode
 | 
						|
{
 | 
						|
    PublisherPage,
 | 
						|
    RealmPage,
 | 
						|
    ReplyPage,
 | 
						|
}
 | 
						|
 | 
						|
public class SnPost : ModelBase, IIdentifiedResource, ITimelineEvent
 | 
						|
{
 | 
						|
    public Guid Id { get; set; }
 | 
						|
 | 
						|
    [MaxLength(1024)]
 | 
						|
    public string? Title { get; set; }
 | 
						|
 | 
						|
    [MaxLength(4096)]
 | 
						|
    public string? Description { get; set; }
 | 
						|
 | 
						|
    [MaxLength(1024)]
 | 
						|
    public string? Slug { get; set; }
 | 
						|
    public Instant? EditedAt { get; set; }
 | 
						|
    public Instant? PublishedAt { get; set; }
 | 
						|
    public PostVisibility Visibility { get; set; } = PostVisibility.Public;
 | 
						|
 | 
						|
    // ReSharper disable once EntityFramework.ModelValidation.UnlimitedStringLength
 | 
						|
    public string? Content { get; set; }
 | 
						|
 | 
						|
    public PostType Type { get; set; }
 | 
						|
    public PostPinMode? PinMode { get; set; }
 | 
						|
 | 
						|
    [Column(TypeName = "jsonb")]
 | 
						|
    public Dictionary<string, object>? Meta { get; set; }
 | 
						|
 | 
						|
    [Column(TypeName = "jsonb")]
 | 
						|
    public List<ContentSensitiveMark>? SensitiveMarks { get; set; } = [];
 | 
						|
 | 
						|
    [Column(TypeName = "jsonb")]
 | 
						|
    public PostEmbedView? EmbedView { get; set; }
 | 
						|
 | 
						|
    public int ViewsUnique { get; set; }
 | 
						|
    public int ViewsTotal { get; set; }
 | 
						|
    public int Upvotes { get; set; }
 | 
						|
    public int Downvotes { get; set; }
 | 
						|
    public decimal AwardedScore { get; set; }
 | 
						|
 | 
						|
    [NotMapped]
 | 
						|
    public Dictionary<string, int> ReactionsCount { get; set; } = new();
 | 
						|
 | 
						|
    [NotMapped]
 | 
						|
    public int RepliesCount { get; set; }
 | 
						|
 | 
						|
    [NotMapped]
 | 
						|
    public Dictionary<string, bool>? ReactionsMade { get; set; }
 | 
						|
 | 
						|
    public bool RepliedGone { get; set; }
 | 
						|
    public bool ForwardedGone { get; set; }
 | 
						|
 | 
						|
    public Guid? RepliedPostId { get; set; }
 | 
						|
    public SnPost? RepliedPost { get; set; }
 | 
						|
    public Guid? ForwardedPostId { get; set; }
 | 
						|
    public SnPost? ForwardedPost { get; set; }
 | 
						|
 | 
						|
    public Guid? RealmId { get; set; }
 | 
						|
 | 
						|
    [NotMapped]
 | 
						|
    public SnRealm? Realm { get; set; }
 | 
						|
 | 
						|
    [Column(TypeName = "jsonb")]
 | 
						|
    public List<SnCloudFileReferenceObject> Attachments { get; set; } = [];
 | 
						|
 | 
						|
    public Guid PublisherId { get; set; }
 | 
						|
    public SnPublisher Publisher { get; set; } = null!;
 | 
						|
 | 
						|
    public List<SnPostAward> Awards { get; set; } = [];
 | 
						|
 | 
						|
    [JsonIgnore]
 | 
						|
    public List<SnPostReaction> Reactions { get; set; } = [];
 | 
						|
    public List<SnPostTag> Tags { get; set; } = [];
 | 
						|
    public List<SnPostCategory> Categories { get; set; } = [];
 | 
						|
 | 
						|
    [JsonIgnore]
 | 
						|
    public List<SnPostCollection> Collections { get; set; } = [];
 | 
						|
    public List<SnPostFeaturedRecord> FeaturedRecords { get; set; } = [];
 | 
						|
 | 
						|
    [JsonIgnore]
 | 
						|
    public bool Empty => Content == null && Attachments.Count == 0 && ForwardedPostId == null;
 | 
						|
 | 
						|
    [NotMapped]
 | 
						|
    public bool IsTruncated { get; set; } = false;
 | 
						|
 | 
						|
    public string ResourceIdentifier => $"post:{Id}";
 | 
						|
 | 
						|
    public Post ToProtoValue()
 | 
						|
    {
 | 
						|
        var proto = new Post
 | 
						|
        {
 | 
						|
            Id = Id.ToString(),
 | 
						|
            Title = Title ?? string.Empty,
 | 
						|
            Description = Description ?? string.Empty,
 | 
						|
            Slug = Slug ?? string.Empty,
 | 
						|
            Visibility = (Proto.PostVisibility)((int)Visibility + 1),
 | 
						|
            Type = (Proto.PostType)((int)Type + 1),
 | 
						|
            ViewsUnique = ViewsUnique,
 | 
						|
            ViewsTotal = ViewsTotal,
 | 
						|
            Upvotes = Upvotes,
 | 
						|
            Downvotes = Downvotes,
 | 
						|
            AwardedScore = (double)AwardedScore,
 | 
						|
            ReactionsCount = { ReactionsCount },
 | 
						|
            RepliesCount = RepliesCount,
 | 
						|
            ReactionsMade = { ReactionsMade ?? new Dictionary<string, bool>() },
 | 
						|
            RepliedGone = RepliedGone,
 | 
						|
            ForwardedGone = ForwardedGone,
 | 
						|
            PublisherId = PublisherId.ToString(),
 | 
						|
            Publisher = Publisher.ToProtoValue(),
 | 
						|
            CreatedAt = Timestamp.FromDateTimeOffset(CreatedAt.ToDateTimeOffset()),
 | 
						|
            UpdatedAt = Timestamp.FromDateTimeOffset(UpdatedAt.ToDateTimeOffset()),
 | 
						|
        };
 | 
						|
 | 
						|
        if (EditedAt.HasValue)
 | 
						|
            proto.EditedAt = Timestamp.FromDateTimeOffset(EditedAt.Value.ToDateTimeOffset());
 | 
						|
 | 
						|
        if (PublishedAt.HasValue)
 | 
						|
            proto.PublishedAt = Timestamp.FromDateTimeOffset(PublishedAt.Value.ToDateTimeOffset());
 | 
						|
 | 
						|
        if (Content != null)
 | 
						|
            proto.Content = Content;
 | 
						|
 | 
						|
        if (PinMode.HasValue)
 | 
						|
            proto.PinMode = (Proto.PostPinMode)((int)PinMode.Value + 1);
 | 
						|
 | 
						|
        if (Meta != null)
 | 
						|
            proto.Meta = GrpcTypeHelper.ConvertObjectToByteString(Meta);
 | 
						|
 | 
						|
        if (SensitiveMarks != null)
 | 
						|
            proto.SensitiveMarks = GrpcTypeHelper.ConvertObjectToByteString(SensitiveMarks);
 | 
						|
 | 
						|
        if (EmbedView != null)
 | 
						|
            proto.EmbedView = EmbedView.ToProtoValue();
 | 
						|
 | 
						|
        if (RepliedPostId.HasValue)
 | 
						|
        {
 | 
						|
            proto.RepliedPostId = RepliedPostId.Value.ToString();
 | 
						|
            if (RepliedPost != null)
 | 
						|
            {
 | 
						|
                proto.RepliedPost = RepliedPost.ToProtoValue();
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (ForwardedPostId.HasValue)
 | 
						|
        {
 | 
						|
            proto.ForwardedPostId = ForwardedPostId.Value.ToString();
 | 
						|
            if (ForwardedPost != null)
 | 
						|
            {
 | 
						|
                proto.ForwardedPost = ForwardedPost.ToProtoValue();
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (RealmId.HasValue)
 | 
						|
        {
 | 
						|
            proto.RealmId = RealmId.Value.ToString();
 | 
						|
            if (Realm != null)
 | 
						|
            {
 | 
						|
                proto.Realm = Realm.ToProtoValue();
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        proto.Attachments.AddRange(Attachments.Select(a => a.ToProtoValue()));
 | 
						|
        proto.Awards.AddRange(Awards.Select(a => a.ToProtoValue()));
 | 
						|
        proto.Reactions.AddRange(Reactions.Select(r => r.ToProtoValue()));
 | 
						|
        proto.Tags.AddRange(Tags.Select(t => t.ToProtoValue()));
 | 
						|
        proto.Categories.AddRange(Categories.Select(c => c.ToProtoValue()));
 | 
						|
        proto.FeaturedRecords.AddRange(FeaturedRecords.Select(f => f.ToProtoValue()));
 | 
						|
 | 
						|
        if (DeletedAt.HasValue)
 | 
						|
            proto.DeletedAt = Timestamp.FromDateTimeOffset(DeletedAt.Value.ToDateTimeOffset());
 | 
						|
 | 
						|
        return proto;
 | 
						|
    }
 | 
						|
 | 
						|
    public static SnPost FromProtoValue(Post proto)
 | 
						|
    {
 | 
						|
        var post = new SnPost
 | 
						|
        {
 | 
						|
            Id = Guid.Parse(proto.Id),
 | 
						|
            Title = string.IsNullOrEmpty(proto.Title) ? null : proto.Title,
 | 
						|
            Description = string.IsNullOrEmpty(proto.Description) ? null : proto.Description,
 | 
						|
            Slug = string.IsNullOrEmpty(proto.Slug) ? null : proto.Slug,
 | 
						|
            Visibility = (PostVisibility)((int)proto.Visibility - 1),
 | 
						|
            Type = (PostType)((int)proto.Type - 1),
 | 
						|
            ViewsUnique = proto.ViewsUnique,
 | 
						|
            ViewsTotal = proto.ViewsTotal,
 | 
						|
            Upvotes = proto.Upvotes,
 | 
						|
            Downvotes = proto.Downvotes,
 | 
						|
            AwardedScore = (decimal)proto.AwardedScore,
 | 
						|
            ReactionsCount = proto.ReactionsCount.ToDictionary(kv => kv.Key, kv => kv.Value),
 | 
						|
            RepliesCount = proto.RepliesCount,
 | 
						|
            ReactionsMade = proto.ReactionsMade.ToDictionary(kv => kv.Key, kv => kv.Value),
 | 
						|
            RepliedGone = proto.RepliedGone,
 | 
						|
            ForwardedGone = proto.ForwardedGone,
 | 
						|
            PublisherId = Guid.Parse(proto.PublisherId),
 | 
						|
            Publisher = SnPublisher.FromProtoValue(proto.Publisher),
 | 
						|
            CreatedAt = Instant.FromDateTimeOffset(proto.CreatedAt.ToDateTimeOffset()),
 | 
						|
            UpdatedAt = Instant.FromDateTimeOffset(proto.UpdatedAt.ToDateTimeOffset()),
 | 
						|
        };
 | 
						|
 | 
						|
        if (proto.EditedAt is not null)
 | 
						|
            post.EditedAt = Instant.FromDateTimeOffset(proto.EditedAt.ToDateTimeOffset());
 | 
						|
 | 
						|
        if (proto.PublishedAt is not null)
 | 
						|
            post.PublishedAt = Instant.FromDateTimeOffset(proto.PublishedAt.ToDateTimeOffset());
 | 
						|
 | 
						|
        if (!string.IsNullOrEmpty(proto.Content))
 | 
						|
            post.Content = proto.Content;
 | 
						|
 | 
						|
        if (proto is { HasPinMode: true, PinMode: > 0 })
 | 
						|
            post.PinMode = (PostPinMode)(proto.PinMode - 1);
 | 
						|
 | 
						|
        if (proto.Meta != null)
 | 
						|
            post.Meta = GrpcTypeHelper.ConvertByteStringToObject<Dictionary<string, object>>(
 | 
						|
                proto.Meta
 | 
						|
            );
 | 
						|
 | 
						|
        if (proto.SensitiveMarks != null)
 | 
						|
            post.SensitiveMarks = GrpcTypeHelper.ConvertByteStringToObject<
 | 
						|
                List<ContentSensitiveMark>
 | 
						|
            >(proto.SensitiveMarks);
 | 
						|
 | 
						|
        if (proto.EmbedView is not null)
 | 
						|
            post.EmbedView = PostEmbedView.FromProtoValue(proto.EmbedView);
 | 
						|
 | 
						|
        if (!string.IsNullOrEmpty(proto.RepliedPostId))
 | 
						|
        {
 | 
						|
            post.RepliedPostId = Guid.Parse(proto.RepliedPostId);
 | 
						|
            if (proto.RepliedPost is not null)
 | 
						|
                post.RepliedPost = FromProtoValue(proto.RepliedPost);
 | 
						|
        }
 | 
						|
 | 
						|
        if (!string.IsNullOrEmpty(proto.ForwardedPostId))
 | 
						|
        {
 | 
						|
            post.ForwardedPostId = Guid.Parse(proto.ForwardedPostId);
 | 
						|
            if (proto.ForwardedPost is not null)
 | 
						|
                post.ForwardedPost = FromProtoValue(proto.ForwardedPost);
 | 
						|
        }
 | 
						|
 | 
						|
        if (!string.IsNullOrEmpty(proto.RealmId))
 | 
						|
        {
 | 
						|
            post.RealmId = Guid.Parse(proto.RealmId);
 | 
						|
            if (proto.Realm is not null)
 | 
						|
                post.Realm = SnRealm.FromProtoValue(proto.Realm);
 | 
						|
        }
 | 
						|
 | 
						|
        post.Attachments.AddRange(
 | 
						|
            proto.Attachments.Select(SnCloudFileReferenceObject.FromProtoValue)
 | 
						|
        );
 | 
						|
        post.Awards.AddRange(
 | 
						|
            proto.Awards.Select(a => new SnPostAward
 | 
						|
            {
 | 
						|
                Id = Guid.Parse(a.Id),
 | 
						|
                PostId = Guid.Parse(a.PostId),
 | 
						|
                AccountId = Guid.Parse(a.AccountId),
 | 
						|
                Amount = (decimal)a.Amount,
 | 
						|
                Attitude = (PostReactionAttitude)((int)a.Attitude - 1),
 | 
						|
                Message = string.IsNullOrEmpty(a.Message) ? null : a.Message,
 | 
						|
                CreatedAt = Instant.FromDateTimeOffset(a.CreatedAt.ToDateTimeOffset()),
 | 
						|
                UpdatedAt = Instant.FromDateTimeOffset(a.UpdatedAt.ToDateTimeOffset()),
 | 
						|
            })
 | 
						|
        );
 | 
						|
        post.Reactions.AddRange(proto.Reactions.Select(SnPostReaction.FromProtoValue));
 | 
						|
        post.Tags.AddRange(proto.Tags.Select(SnPostTag.FromProtoValue));
 | 
						|
        post.Categories.AddRange(proto.Categories.Select(SnPostCategory.FromProtoValue));
 | 
						|
        post.FeaturedRecords.AddRange(
 | 
						|
            proto.FeaturedRecords.Select(SnPostFeaturedRecord.FromProtoValue)
 | 
						|
        );
 | 
						|
 | 
						|
        if (proto.DeletedAt is not null)
 | 
						|
            post.DeletedAt = Instant.FromDateTimeOffset(proto.DeletedAt.ToDateTimeOffset());
 | 
						|
 | 
						|
        return post;
 | 
						|
    }
 | 
						|
 | 
						|
    public SnTimelineEvent ToActivity()
 | 
						|
    {
 | 
						|
        return new SnTimelineEvent()
 | 
						|
        {
 | 
						|
            CreatedAt = PublishedAt ?? CreatedAt,
 | 
						|
            UpdatedAt = UpdatedAt,
 | 
						|
            DeletedAt = DeletedAt,
 | 
						|
            Id = Id,
 | 
						|
            Type = RepliedPostId is null ? "posts.new" : "posts.new.replies",
 | 
						|
            ResourceIdentifier = ResourceIdentifier,
 | 
						|
            Data = this,
 | 
						|
        };
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
public class SnPostTag : ModelBase
 | 
						|
{
 | 
						|
    public Guid Id { get; set; }
 | 
						|
 | 
						|
    [MaxLength(128)]
 | 
						|
    public string Slug { get; set; } = null!;
 | 
						|
 | 
						|
    [MaxLength(256)]
 | 
						|
    public string? Name { get; set; }
 | 
						|
 | 
						|
    [JsonIgnore]
 | 
						|
    public List<SnPost> Posts { get; set; } = new List<SnPost>();
 | 
						|
 | 
						|
    [NotMapped]
 | 
						|
    public int? Usage { get; set; }
 | 
						|
 | 
						|
    public PostTag ToProtoValue()
 | 
						|
    {
 | 
						|
        return new PostTag
 | 
						|
        {
 | 
						|
            Id = Id.ToString(),
 | 
						|
            Slug = Slug,
 | 
						|
            Name = Name ?? string.Empty,
 | 
						|
            CreatedAt = Timestamp.FromDateTimeOffset(CreatedAt.ToDateTimeOffset()),
 | 
						|
            UpdatedAt = Timestamp.FromDateTimeOffset(UpdatedAt.ToDateTimeOffset()),
 | 
						|
        };
 | 
						|
    }
 | 
						|
 | 
						|
    public static SnPostTag FromProtoValue(PostTag proto)
 | 
						|
    {
 | 
						|
        return new SnPostTag
 | 
						|
        {
 | 
						|
            Id = Guid.Parse(proto.Id),
 | 
						|
            Slug = proto.Slug,
 | 
						|
            Name = proto.Name != string.Empty ? proto.Name : null,
 | 
						|
            CreatedAt = Instant.FromDateTimeOffset(proto.CreatedAt.ToDateTimeOffset()),
 | 
						|
            UpdatedAt = Instant.FromDateTimeOffset(proto.UpdatedAt.ToDateTimeOffset()),
 | 
						|
        };
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
public class SnPostCategory : ModelBase
 | 
						|
{
 | 
						|
    public Guid Id { get; set; }
 | 
						|
 | 
						|
    [MaxLength(128)]
 | 
						|
    public string Slug { get; set; } = null!;
 | 
						|
 | 
						|
    [MaxLength(256)]
 | 
						|
    public string? Name { get; set; }
 | 
						|
 | 
						|
    [JsonIgnore]
 | 
						|
    public List<SnPost> Posts { get; set; } = new List<SnPost>();
 | 
						|
 | 
						|
    [NotMapped]
 | 
						|
    public int? Usage { get; set; }
 | 
						|
 | 
						|
    public PostCategory ToProtoValue()
 | 
						|
    {
 | 
						|
        return new PostCategory
 | 
						|
        {
 | 
						|
            Id = Id.ToString(),
 | 
						|
            Slug = Slug,
 | 
						|
            Name = Name ?? string.Empty,
 | 
						|
            CreatedAt = Timestamp.FromDateTimeOffset(CreatedAt.ToDateTimeOffset()),
 | 
						|
            UpdatedAt = Timestamp.FromDateTimeOffset(UpdatedAt.ToDateTimeOffset()),
 | 
						|
        };
 | 
						|
    }
 | 
						|
 | 
						|
    public static SnPostCategory FromProtoValue(PostCategory proto)
 | 
						|
    {
 | 
						|
        return new SnPostCategory
 | 
						|
        {
 | 
						|
            Id = Guid.Parse(proto.Id),
 | 
						|
            Slug = proto.Slug,
 | 
						|
            Name = proto.Name != string.Empty ? proto.Name : null,
 | 
						|
            CreatedAt = Instant.FromDateTimeOffset(proto.CreatedAt.ToDateTimeOffset()),
 | 
						|
            UpdatedAt = Instant.FromDateTimeOffset(proto.UpdatedAt.ToDateTimeOffset()),
 | 
						|
        };
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
public class SnPostCategorySubscription : ModelBase
 | 
						|
{
 | 
						|
    public Guid Id { get; set; }
 | 
						|
    public Guid AccountId { get; set; }
 | 
						|
 | 
						|
    public Guid? CategoryId { get; set; }
 | 
						|
    public SnPostCategory? Category { get; set; }
 | 
						|
    public Guid? TagId { get; set; }
 | 
						|
    public SnPostTag? Tag { get; set; }
 | 
						|
}
 | 
						|
 | 
						|
public class SnPostCollection : ModelBase
 | 
						|
{
 | 
						|
    public Guid Id { get; set; }
 | 
						|
 | 
						|
    [MaxLength(128)]
 | 
						|
    public string Slug { get; set; } = null!;
 | 
						|
 | 
						|
    [MaxLength(256)]
 | 
						|
    public string? Name { get; set; }
 | 
						|
 | 
						|
    [MaxLength(4096)]
 | 
						|
    public string? Description { get; set; }
 | 
						|
 | 
						|
    public SnPublisher Publisher { get; set; } = null!;
 | 
						|
 | 
						|
    public List<SnPost> Posts { get; set; } = new List<SnPost>();
 | 
						|
}
 | 
						|
 | 
						|
public class SnPostFeaturedRecord : ModelBase
 | 
						|
{
 | 
						|
    public Guid Id { get; set; }
 | 
						|
    public Guid PostId { get; set; }
 | 
						|
 | 
						|
    [JsonIgnore]
 | 
						|
    public SnPost Post { get; set; } = null!;
 | 
						|
    public Instant? FeaturedAt { get; set; }
 | 
						|
    public int SocialCredits { get; set; }
 | 
						|
 | 
						|
    public PostFeaturedRecord ToProtoValue()
 | 
						|
    {
 | 
						|
        var proto = new PostFeaturedRecord
 | 
						|
        {
 | 
						|
            Id = Id.ToString(),
 | 
						|
            PostId = PostId.ToString(),
 | 
						|
            SocialCredits = SocialCredits,
 | 
						|
            CreatedAt = Timestamp.FromDateTimeOffset(CreatedAt.ToDateTimeOffset()),
 | 
						|
            UpdatedAt = Timestamp.FromDateTimeOffset(UpdatedAt.ToDateTimeOffset()),
 | 
						|
        };
 | 
						|
        if (FeaturedAt.HasValue)
 | 
						|
        {
 | 
						|
            proto.FeaturedAt = Timestamp.FromDateTimeOffset(FeaturedAt.Value.ToDateTimeOffset());
 | 
						|
        }
 | 
						|
 | 
						|
        return proto;
 | 
						|
    }
 | 
						|
 | 
						|
    public static SnPostFeaturedRecord FromProtoValue(PostFeaturedRecord proto)
 | 
						|
    {
 | 
						|
        return new SnPostFeaturedRecord
 | 
						|
        {
 | 
						|
            Id = Guid.Parse(proto.Id),
 | 
						|
            PostId = Guid.Parse(proto.PostId),
 | 
						|
            SocialCredits = proto.SocialCredits,
 | 
						|
            CreatedAt = Instant.FromDateTimeOffset(proto.CreatedAt.ToDateTimeOffset()),
 | 
						|
            UpdatedAt = Instant.FromDateTimeOffset(proto.UpdatedAt.ToDateTimeOffset()),
 | 
						|
            FeaturedAt =
 | 
						|
                proto.FeaturedAt != null
 | 
						|
                    ? Instant.FromDateTimeOffset(proto.FeaturedAt.ToDateTimeOffset())
 | 
						|
                    : null,
 | 
						|
        };
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
public enum PostReactionAttitude
 | 
						|
{
 | 
						|
    Positive,
 | 
						|
    Neutral,
 | 
						|
    Negative,
 | 
						|
}
 | 
						|
 | 
						|
public class SnPostReaction : ModelBase
 | 
						|
{
 | 
						|
    public Guid Id { get; set; }
 | 
						|
 | 
						|
    [MaxLength(256)]
 | 
						|
    public string Symbol { get; set; } = null!;
 | 
						|
    public PostReactionAttitude Attitude { get; set; }
 | 
						|
 | 
						|
    public Guid PostId { get; set; }
 | 
						|
 | 
						|
    [JsonIgnore]
 | 
						|
    public SnPost Post { get; set; } = null!;
 | 
						|
    public Guid AccountId { get; set; }
 | 
						|
 | 
						|
    [NotMapped]
 | 
						|
    public SnAccount? Account { get; set; }
 | 
						|
 | 
						|
    public PostReaction ToProtoValue()
 | 
						|
    {
 | 
						|
        var proto = new PostReaction
 | 
						|
        {
 | 
						|
            Id = Id.ToString(),
 | 
						|
            Symbol = Symbol,
 | 
						|
            Attitude = (Proto.PostReactionAttitude)((int)Attitude + 1),
 | 
						|
            PostId = PostId.ToString(),
 | 
						|
            AccountId = AccountId.ToString(),
 | 
						|
            CreatedAt = Timestamp.FromDateTimeOffset(CreatedAt.ToDateTimeOffset()),
 | 
						|
            UpdatedAt = Timestamp.FromDateTimeOffset(UpdatedAt.ToDateTimeOffset()),
 | 
						|
        };
 | 
						|
        if (Account != null)
 | 
						|
        {
 | 
						|
            proto.Account = Account.ToProtoValue();
 | 
						|
        }
 | 
						|
 | 
						|
        return proto;
 | 
						|
    }
 | 
						|
 | 
						|
    public static SnPostReaction FromProtoValue(Proto.PostReaction proto)
 | 
						|
    {
 | 
						|
        return new SnPostReaction
 | 
						|
        {
 | 
						|
            Id = Guid.Parse(proto.Id),
 | 
						|
            Symbol = proto.Symbol,
 | 
						|
            Attitude = (PostReactionAttitude)((int)proto.Attitude - 1),
 | 
						|
            PostId = Guid.Parse(proto.PostId),
 | 
						|
            AccountId = Guid.Parse(proto.AccountId),
 | 
						|
            Account = proto.Account != null ? SnAccount.FromProtoValue(proto.Account) : null,
 | 
						|
            CreatedAt = Instant.FromDateTimeOffset(proto.CreatedAt.ToDateTimeOffset()),
 | 
						|
            UpdatedAt = Instant.FromDateTimeOffset(proto.UpdatedAt.ToDateTimeOffset()),
 | 
						|
        };
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
public class SnPostAward : ModelBase
 | 
						|
{
 | 
						|
    public Guid Id { get; set; }
 | 
						|
    public decimal Amount { get; set; }
 | 
						|
    public PostReactionAttitude Attitude { get; set; }
 | 
						|
 | 
						|
    [MaxLength(4096)]
 | 
						|
    public string? Message { get; set; }
 | 
						|
 | 
						|
    public Guid PostId { get; set; }
 | 
						|
 | 
						|
    [JsonIgnore]
 | 
						|
    public SnPost Post { get; set; } = null!;
 | 
						|
    public Guid AccountId { get; set; }
 | 
						|
 | 
						|
    public PostAward ToProtoValue()
 | 
						|
    {
 | 
						|
        var proto = new PostAward
 | 
						|
        {
 | 
						|
            Id = Id.ToString(),
 | 
						|
            Amount = (double)Amount,
 | 
						|
            Attitude = (Proto.PostReactionAttitude)((int)Attitude + 1),
 | 
						|
            PostId = PostId.ToString(),
 | 
						|
            AccountId = AccountId.ToString(),
 | 
						|
            CreatedAt = Timestamp.FromDateTimeOffset(CreatedAt.ToDateTimeOffset()),
 | 
						|
            UpdatedAt = Timestamp.FromDateTimeOffset(UpdatedAt.ToDateTimeOffset()),
 | 
						|
        };
 | 
						|
        if (Message != null)
 | 
						|
            proto.Message = Message;
 | 
						|
        return proto;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/// <summary>
 | 
						|
/// This model is used to tell the client to render a WebView / iframe
 | 
						|
/// Usually external website and web pages
 | 
						|
/// Used as a JSON column
 | 
						|
/// </summary>
 | 
						|
public class PostEmbedView
 | 
						|
{
 | 
						|
    public string Uri { get; set; } = null!;
 | 
						|
    public double? AspectRatio { get; set; }
 | 
						|
    public PostEmbedViewRenderer Renderer { get; set; } = PostEmbedViewRenderer.WebView;
 | 
						|
 | 
						|
    public Proto.PostEmbedView ToProtoValue()
 | 
						|
    {
 | 
						|
        var proto = new Proto.PostEmbedView
 | 
						|
        {
 | 
						|
            Uri = Uri,
 | 
						|
            Renderer = (Proto.PostEmbedViewRenderer)(int)Renderer,
 | 
						|
        };
 | 
						|
        if (AspectRatio.HasValue)
 | 
						|
        {
 | 
						|
            proto.AspectRatio = AspectRatio.Value;
 | 
						|
        }
 | 
						|
 | 
						|
        return proto;
 | 
						|
    }
 | 
						|
 | 
						|
    public static PostEmbedView FromProtoValue(Proto.PostEmbedView proto)
 | 
						|
    {
 | 
						|
        return new PostEmbedView
 | 
						|
        {
 | 
						|
            Uri = proto.Uri,
 | 
						|
            AspectRatio = proto.HasAspectRatio ? proto.AspectRatio : null,
 | 
						|
            Renderer = (PostEmbedViewRenderer)((int)proto.Renderer - 1),
 | 
						|
        };
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
public enum PostEmbedViewRenderer
 | 
						|
{
 | 
						|
    WebView,
 | 
						|
}
 |