using Govor.Application.Interfaces; using Govor.Application.Interfaces.Medias; using Govor.Core.Models; using Govor.Data; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace Govor.Application.Services.Medias; public class MediaService : IMediaService { private ILogger _logger; private IStorageService _storageService; private GovorDbContext _dbContext; public MediaService(IStorageService storageService, GovorDbContext dbContext, ILogger logger) { _storageService = storageService; _dbContext = dbContext; _logger = logger; } public async Task UploadMediaAsync(Media file) { try { var url = await _storageService.SaveAsync(file.Data, file.FileName); var mediaId = Guid.NewGuid(); _dbContext.MediaFiles.Add(new MediaFile() { Id = mediaId, UploaderId = file.UploaderId, DateCreated = file.UploadedOn, MediaType = file.Type, MineType = file.MimeType, Url = url, OwnerType = file.OwnerType, OwnerId = file.OwnerId, }); await _dbContext.SaveChangesAsync(); _logger.LogInformation($"Media uploaded: {url} with id: {mediaId} by {file.UploaderId}"); return new MediaUploadResult(mediaId, url); } catch (ArgumentException ex) { throw new InvalidOperationException($"An error occured while uploading the media file: {ex.Message}"); } } public Task DeleteMediaAsync(Guid fileId) { throw new NotImplementedException(); } public Task GetMediaByUrlAsync(string url) { throw new NotImplementedException(); } public async Task GetMediaByIdAsync(Guid mediaId) { try { var mediaFile = await _dbContext.MediaFiles .AsNoTracking() .FirstOrDefaultAsync(x => x.Id == mediaId) ?? throw new KeyNotFoundException($"No media found by given id {mediaId}"); // Загрузить бинарные данные из хранилища Stream dataStream = await _storageService.LoadAsync(mediaFile.Url); // Считать поток в byte[] using var memoryStream = new MemoryStream(); await dataStream.CopyToAsync(memoryStream); var contentBytes = memoryStream.ToArray(); _logger.LogInformation($"Media found: {mediaFile.MediaType} with id: {mediaFile.Id} and url: {mediaFile.Url}"); // Вернуть объект Media return new Media( mediaFile.UploaderId, mediaFile.DateCreated, mediaFile.MediaType.ToString(), contentBytes, mediaFile.MediaType, mediaFile.MineType, string.Empty, mediaFile.OwnerType, mediaFile.OwnerId ); } catch (FileNotFoundException ex) { _logger.LogWarning(ex, "Media file not found on storage."); throw; } } public async Task AttachToMessageAsync(Guid mediaId, Guid messageId) { var mediaFile = await _dbContext.MediaFiles .FirstOrDefaultAsync(x => x.Id == mediaId) ?? throw new KeyNotFoundException($"No media found by given id {mediaId}"); if (mediaFile.OwnerType != MediaOwnerType.Message) { _logger.LogWarning("Attempt to attach already owned media {MediaId}", mediaId); throw new InvalidOperationException($"Media {mediaId} is already attached to {mediaFile.OwnerType}"); } mediaFile.OwnerType = MediaOwnerType.Message; mediaFile.OwnerId = messageId; _dbContext.MediaFiles.Update(mediaFile); await _dbContext.SaveChangesAsync(); _logger.LogInformation("Media {MediaId} successfully attached to message {MessageId}", mediaId, messageId); } }