внедрил пресеты статусов и модульную архитектуру

This commit is contained in:
max
2026-04-18 00:43:46 +03:00
parent e8c9a55fe9
commit f4f61071ed
32 changed files with 665 additions and 110 deletions

View File

@@ -10,29 +10,39 @@ namespace Knot.Modules.Profiles.Infrastructure.Database;
internal class ProfileRepository : IProfileRepository
{
private readonly IMongoCollection<ProfileDocument> _profiles;
private readonly IUserStatusRepository _statuses;
public ProfileRepository(IMongoDatabase database)
public ProfileRepository(IMongoDatabase database, IUserStatusRepository statuses)
{
_profiles = database.GetCollection<ProfileDocument>("profiles");
_statuses = statuses;
}
public async Task<UserProfileDto?> GetAsync(Guid userId, CancellationToken ct = default)
{
var profile = await _profiles.Find(p => p.Id == userId).FirstOrDefaultAsync(ct);
return profile?.ToDto();
return profile is null ? null : await profile.ToDtoAsync(_statuses, ct);
}
public async Task<UserProfileDto?> GetByUsernameAsync(string username, CancellationToken ct = default)
{
var profile = await _profiles.Find(p => p.Username == username).FirstOrDefaultAsync(ct);
return profile?.ToDto();
return profile is null ? null : await profile.ToDtoAsync(_statuses, ct);
}
public async Task<List<UserProfileDto>> GetAsync(IEnumerable<Guid> userIds, CancellationToken ct = default)
{
var ids = userIds.ToList();
var profiles = await _profiles.Find(p => ids.Contains(p.Id)).ToListAsync(ct);
return profiles.Select(p => p.ToDto()).ToList();
var statusIds = profiles
.Where(p => p.CurrentStatusId.HasValue)
.Select(p => p.CurrentStatusId!.Value)
.Distinct()
.ToList();
var map = statusIds.Count > 0
? await _statuses.GetByIdsAsync(statusIds, ct)
: new Dictionary<Guid, UserStatusDto>();
return profiles.Select(p => ProfileMappings.ToDtoWithStatusMap(p, map)).ToList();
}
public async Task<List<UserProfileDto>> SearchAsync(string query, int limit = 20, CancellationToken ct = default)
@@ -57,7 +67,16 @@ internal class ProfileRepository : IProfileRepository
var combinedFilter = Builders<ProfileDocument>.Filter.And(baseFilter, searchFilter);
docs = await _profiles.Find(combinedFilter).Limit(limit).ToListAsync(ct);
}
return docs.Select(p => p.ToDto()).ToList();
var statusIds = docs
.Where(p => p.CurrentStatusId.HasValue)
.Select(p => p.CurrentStatusId!.Value)
.Distinct()
.ToList();
var map = statusIds.Count > 0
? await _statuses.GetByIdsAsync(statusIds, ct)
: new Dictionary<Guid, UserStatusDto>();
return docs.Select(p => ProfileMappings.ToDtoWithStatusMap(p, map)).ToList();
}
public async Task<Result<UserProfileDto>> CreateAsync(UserProfileDto dto, CancellationToken ct = default)
@@ -65,7 +84,7 @@ internal class ProfileRepository : IProfileRepository
var profile = ProfileDocument.Create(dto.UserId, dto.Username ?? string.Empty, dto.DisplayName ?? string.Empty, dto.About);
await _profiles.InsertOneAsync(profile, null, ct);
return Result.Success(profile.ToDto());
return Result.Success(await profile.ToDtoAsync(_statuses, ct));
}
public async Task<Result<UserProfileDto>> UpdateAsync(UserProfileDto dto, CancellationToken ct = default)
@@ -80,11 +99,13 @@ internal class ProfileRepository : IProfileRepository
dto.Birthday);
document.UpdateAvatar(dto.Avatar);
document.UpdateStatus(dto.StatusText, dto.StatusEmoji, dto.StatusExpiresAt);
document.UpdateInvisible(dto.IsInvisible);
await _profiles.ReplaceOneAsync(p => p.Id == dto.UserId, document, cancellationToken: ct);
return Result.Success(document.ToDto());
var fresh = await _profiles.Find(p => p.Id == dto.UserId).FirstOrDefaultAsync(ct);
if (fresh is null)
return Result.Failure<UserProfileDto>(ProfilesErrors.ProfileNotFound);
return Result.Success(await fresh.ToDtoAsync(_statuses, ct));
}
public async Task<Result> UpdateStatusAsync(Guid userId, bool isBanned, bool isDeleted, CancellationToken ct = default)