using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Text.Json.Serialization; using DysonNetwork.Shared.Proto; using NodaTime; using NodaTime.Serialization.Protobuf; namespace DysonNetwork.Shared.Models; public class SnCloudFile : ModelBase, ICloudFile, IIdentifiedResource { /// The id generated by TuS, basically just UUID remove the dash lines [MaxLength(32)] public string Id { get; set; } = Guid.NewGuid().ToString().Replace("-", string.Empty); [MaxLength(1024)] public string Name { get; set; } [MaxLength(4096)] public string? Description { get; set; } [Column(TypeName = "jsonb")] public Dictionary? UserMeta { get; set; } [Column(TypeName = "jsonb")] public List? SensitiveMarks { get; set; } = []; [NotMapped] [Column(TypeName = "jsonb")] public Dictionary FileMeta => Object!.Meta ?? []; [NotMapped] [MaxLength(256)] public string? MimeType => Object!.MimeType; [NotMapped] [MaxLength(256)] public string? Hash => Object!.Hash; public Instant? ExpiredAt { get; set; } [NotMapped] public long Size => Object!.Size; public Instant? UploadedAt { get; set; } [NotMapped] public bool HasCompression => Object!.HasCompression; [NotMapped] public bool HasThumbnail => Object!.HasThumbnail; [MaxLength(32)] public string? ObjectId { get; set; } public SnFileObject? Object { get; set; } public FilePool? Pool { get; set; } public Guid? PoolId { get; set; } [JsonIgnore] public SnFileBundle? Bundle { get; set; } public Guid? BundleId { get; set; } [JsonIgnore] public List FileIndexes { get; set; } = []; /// /// The field is set to true if the recycling job plans to delete the file. /// Due to the unstable of the recycling job, this doesn't really delete the file until a human verifies it. /// public bool IsMarkedRecycle { get; set; } = false; /// The object name which stored remotely, /// multiple cloud file may have same storage id to indicate they are the same file /// /// If the storage id was null and the uploaded at is not null, means it is an embedding file, /// The embedding file means the file is store on another site, /// or it is a webpage (based on mimetype) [MaxLength(32)] public string? StorageId { get; set; } /// This field should be null when the storage id is filled /// Indicates the off-site accessible url of the file [MaxLength(4096)] public string? StorageUrl { get; set; } [NotMapped] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? FastUploadLink { get; set; } public Guid AccountId { get; set; } public SnCloudFileReferenceObject ToReferenceObject() { return new SnCloudFileReferenceObject { CreatedAt = CreatedAt, UpdatedAt = UpdatedAt, DeletedAt = DeletedAt, Id = Id, Name = Name, FileMeta = FileMeta ?? [], UserMeta = UserMeta ?? [], SensitiveMarks = SensitiveMarks, MimeType = MimeType, Hash = Hash, Size = Size, HasCompression = HasCompression }; } public string ResourceIdentifier => $"file:{Id}"; /// /// Converts the CloudFile to a protobuf message /// /// The protobuf message representation of this object public CloudFile ToProtoValue() { var proto = new CloudFile { Id = Id, Name = Name, MimeType = MimeType ?? string.Empty, Hash = Hash ?? string.Empty, Size = Size, HasCompression = HasCompression, Url = StorageUrl ?? string.Empty, ContentType = MimeType ?? string.Empty, UploadedAt = UploadedAt?.ToTimestamp(), // Convert file metadata FileMeta = GrpcTypeHelper.ConvertObjectToByteString(FileMeta), // Convert user metadata UserMeta = GrpcTypeHelper.ConvertObjectToByteString(UserMeta), SensitiveMarks = GrpcTypeHelper.ConvertObjectToByteString(SensitiveMarks) }; return proto; } }