mirror of
https://github.com/RedWizardsLab/EchoHub.git
synced 2026-09-05 23:34:09 +02:00
feat: Add support for message attachments
- Introduced Attachment model to handle file attachments associated with messages. - Updated ModerationController to manage message deletions and attachment cleanup. - Enhanced ChatService to include attachments in message retrieval. - Implemented migration for legacy single-attachment messages to the new Attachments model. - Added unit tests for attachment handling in message formatting and parsing. - Updated database context and migrations to support new Attachments table.
This commit is contained in:
@@ -11,6 +11,7 @@ public static class HubConstants
|
||||
public const int MaxFileSizeBytes = 100 * 1024 * 1024; // 100 MB
|
||||
public const int MaxAvatarSizeBytes = 2 * 1024 * 1024; // 2 MB
|
||||
public const int MaxMessageNewlines = 30;
|
||||
public const int MaxAttachmentsPerMessage = 10;
|
||||
public const int MaxConsecutiveNewlines = 1;
|
||||
public const int AsciiArtWidth = 80;
|
||||
public const int AsciiArtHeight = 40;
|
||||
|
||||
@@ -8,13 +8,22 @@ public record MessageDto(
|
||||
string SenderUsername,
|
||||
string? SenderNicknameColor,
|
||||
string ChannelName,
|
||||
MessageType Type,
|
||||
string? AttachmentUrl,
|
||||
string? AttachmentFileName,
|
||||
DateTimeOffset SentAt,
|
||||
long? AttachmentFileSize = null,
|
||||
List<AttachmentDto>? Attachments = null,
|
||||
List<EmbedDto>? Embeds = null);
|
||||
|
||||
/// <summary>
|
||||
/// A file attached to a message. <see cref="AsciiPreview"/> holds the color-tag art for
|
||||
/// images (null otherwise). For end-to-end encrypted channels the content behind
|
||||
/// <see cref="Url"/> and the preview are ciphertext the server cannot read.
|
||||
/// </summary>
|
||||
public record AttachmentDto(
|
||||
AttachmentKind Kind,
|
||||
string Url,
|
||||
string FileName,
|
||||
long FileSize,
|
||||
string? AsciiPreview = null);
|
||||
|
||||
public record ChannelDto(
|
||||
Guid Id,
|
||||
string Name,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace EchoHub.Core.Models;
|
||||
|
||||
/// <summary>
|
||||
/// A file attached to a message (image, audio, or any file). A message may carry
|
||||
/// zero or more attachments alongside its text content (Discord-style).
|
||||
/// </summary>
|
||||
public class Attachment
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid MessageId { get; set; }
|
||||
public Message? Message { get; set; }
|
||||
|
||||
public AttachmentKind Kind { get; set; }
|
||||
|
||||
/// <summary>Relative download URL, e.g. <c>/api/files/{fileId}</c>.</summary>
|
||||
public required string Url { get; set; }
|
||||
public required string FileName { get; set; }
|
||||
|
||||
/// <summary>Stored blob size in bytes (ciphertext size for encrypted channels).</summary>
|
||||
public long FileSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Rendered ASCII-art preview for images (color-tag format). Null for audio/files.
|
||||
/// Stored encrypted-at-rest when database encryption is enabled, and room-encrypted
|
||||
/// for end-to-end encrypted channels.
|
||||
/// </summary>
|
||||
public string? AsciiPreview { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace EchoHub.Core.Models;
|
||||
|
||||
/// <summary>
|
||||
/// The kind of a message attachment. Determines how the client renders it
|
||||
/// (ASCII preview for images, a play affordance for audio, a download line for files).
|
||||
/// </summary>
|
||||
public enum AttachmentKind
|
||||
{
|
||||
Image,
|
||||
Audio,
|
||||
File
|
||||
}
|
||||
@@ -3,11 +3,10 @@ namespace EchoHub.Core.Models;
|
||||
public class Message
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>The message text/caption. May be empty when the message only carries attachments.</summary>
|
||||
public required string Content { get; set; }
|
||||
public MessageType Type { get; set; } = MessageType.Text;
|
||||
public string? AttachmentUrl { get; set; }
|
||||
public string? AttachmentFileName { get; set; }
|
||||
public long? AttachmentFileSize { get; set; }
|
||||
|
||||
public string? EmbedJson { get; set; }
|
||||
public DateTimeOffset SentAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
|
||||
@@ -16,4 +15,16 @@ public class Message
|
||||
|
||||
public Guid SenderUserId { get; set; }
|
||||
public required string SenderUsername { get; set; }
|
||||
|
||||
/// <summary>Files attached to this message. Empty for a plain text message.</summary>
|
||||
public List<Attachment> Attachments { get; set; } = [];
|
||||
|
||||
// ── Legacy columns (pre-attachments model) ──────────────────────────────
|
||||
// Retained so the one-time startup data migration can fold old single-attachment
|
||||
// messages into Attachments. New code never writes these; they are nulled out
|
||||
// once migrated. Not exposed in DTOs. See DataMigrationService.MigrateLegacyAttachmentsAsync.
|
||||
public MessageType Type { get; set; } = MessageType.Text;
|
||||
public string? AttachmentUrl { get; set; }
|
||||
public string? AttachmentFileName { get; set; }
|
||||
public long? AttachmentFileSize { get; set; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user