feat: add /meta command for channel metadata retrieval

- Implemented the `/meta` command to fetch and display channel metadata including room ID, topic, message count, unique user count, estimated size, and protection level.
- Added `ChannelMetaDto` to encapsulate channel metadata.
- Updated `ChannelsController` to handle the new `/meta` endpoint.
- Introduced `UploadLimits` configuration for admin-defined upload size limits for files, images, audio, and avatars.
- Enhanced error handling and user feedback for metadata retrieval.
- Updated documentation to reflect changes in encryption and room metadata.
- Added tests for the new functionality and upload limits.
This commit is contained in:
HueByte
2026-07-16 07:04:58 +02:00
parent dbf6565d18
commit e797ec2542
22 changed files with 526 additions and 93 deletions
@@ -288,6 +288,42 @@ public class ChannelService : IChannelService
c.PasswordHash != null, c.WrappedRoomKey != null);
}
public async Task<ChannelMetaDto?> GetChannelMetaAsync(string channelName)
{
channelName = channelName.ToLowerInvariant().Trim();
using var scope = _scopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<EchoHubDbContext>();
var c = await db.Channels.FirstOrDefaultAsync(ch => ch.Name == channelName);
if (c is null) return null;
var messageCount = await db.Messages.CountAsync(m => m.ChannelId == c.Id);
// Distinct senders that have posted here. Works the same for encrypted channels —
// sender identity is metadata the server keeps even when it can't read the messages.
var uniqueUsers = await db.Messages
.Where(m => m.ChannelId == c.Id)
.Select(m => m.SenderUserId)
.Distinct()
.CountAsync();
// Estimated footprint: stored attachment blob sizes + message text length. For encrypted
// channels these are the ciphertext sizes, which is the server's real on-disk cost.
var attachmentBytes = await db.Messages
.Where(m => m.ChannelId == c.Id)
.SelectMany(m => m.Attachments)
.SumAsync(a => (long?)a.FileSize) ?? 0;
var textBytes = await db.Messages
.Where(m => m.ChannelId == c.Id)
.SumAsync(m => (long?)m.Content.Length) ?? 0;
return new ChannelMetaDto(
c.Id, c.Name, c.Topic,
c.WrappedRoomKey != null, c.PasswordHash != null,
messageCount, uniqueUsers, attachmentBytes + textBytes, c.CreatedAt);
}
public async Task<ChannelCryptoDto?> GetChannelCryptoAsync(string channelName)
{
channelName = channelName.ToLowerInvariant().Trim();