using decePubClient.Helpers; using decePubClient.Models; using decePubClient.Models.Types; using Markdig; namespace decePubClient.Services { public interface IStorage { ValueTask> GetMessages(); ValueTask GetMessage(string messageId); ValueTask AddMessages(List messages); ValueTask UpdateMessages(List messages); ValueTask RemoveMessage(string messageId); ValueTask> GetClientLogs(); ValueTask AddLog(Exception exception, string where); ValueTask AddLog(string message, string where); ValueTask RemoveAll(bool includeClientLogs = false); } public class Storage : IStorage { readonly IndexedDb _db; readonly ILogger _logger; public Storage(IndexedDb indexedDb, ILogger logger) { _db = indexedDb; _logger = logger; } #region Messagges public async ValueTask GetMessage(string messageId) { await _db.OpenIndexedDb(); var message = await _db.GetByKey(nameof(Message), messageId); if (message is null) { var messages = await GetMessages(); return messages.FirstOrDefault(m => m.MessageId == messageId); } return message; } public async ValueTask> GetMessages() { await _db.OpenIndexedDb(); var messages = await _db.GetAll(nameof(Message)) ?? new(); if (messages.Count == 0) { messages.Add(new() { RootMessageId = default, MessageId = "992167EE-8947-4823-B1E2-B4E1019B6974", User = Faker.GetRandomUser(), MessageType = (MessageType)Random.Shared.Next(0, 4), Title = default, Content = "test di messaggio normale senza titolo", Medias = new(), CreatedAt = DateTime.UtcNow.AddMinutes(Random.Shared.Next(-5000, 0)), IsFavourite = Random.Shared.Next() % 2 == 0, BoostsCounter = Random.Shared.Next(0, 100), IsBoostedByCurrentUser = Random.Shared.Next() % 2 == 0, }); messages.Add(new() { RootMessageId = default, MessageId = "C5307644-4EA8-4B5F-A240-7CFE4DE34741", User = Faker.GetRandomUser(), MessageType = (MessageType)Random.Shared.Next(0, 4), Title = "sopra la panca la capra canta", Content = Markdown.ToHtml("test di messaggio con titolo"), Medias = new(), CreatedAt = DateTime.UtcNow.AddMinutes(Random.Shared.Next(-5000, 0)), IsFavourite = Random.Shared.Next() % 2 == 0, BoostsCounter = Random.Shared.Next(0, 100), IsBoostedByCurrentUser = Random.Shared.Next() % 2 == 0, }); messages.Add(new() { RootMessageId = default, MessageId = "E473D562-D210-4453-93DA-157D4B90B0D8", User = Faker.GetRandomUser(), MessageType = (MessageType)Random.Shared.Next(0, 4), Title = default, Content = "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd test di messaggio con overflow del testo", Medias = new(), CreatedAt = DateTime.UtcNow.AddMinutes(Random.Shared.Next(-5000, 0)), IsFavourite = Random.Shared.Next() % 2 == 0, BoostsCounter = Random.Shared.Next(0, 100), IsBoostedByCurrentUser = Random.Shared.Next() % 2 == 0, }); messages.Add(new() { RootMessageId = default, MessageId = "adf89dc6-0484-430e-a7c9-fcb1179b0c28", User = Faker.GetRandomUser(), MessageType = (MessageType)Random.Shared.Next(0, 4), Title = default, Content = "test video", Medias = new() { new() { FileName = "8252d175e714db88beb8ee0349dbac90405d3d5148e96e0cfd7de3b0876dbb1b.mp4", Url = "https://ihatebeinga.live/media/8252d175e714db88beb8ee0349dbac90405d3d5148e96e0cfd7de3b0876dbb1b.mp4", AltText = "https://ihatebeinga.live/media/8252d175e714db88beb8ee0349dbac90405d3d5148e96e0cfd7de3b0876dbb1b.mp4", ContentType = "video/mp4" } }, CreatedAt = DateTime.UtcNow.AddMinutes(Random.Shared.Next(-5000, 0)), IsFavourite = Random.Shared.Next() % 2 == 0, BoostsCounter = Random.Shared.Next(0, 100), IsBoostedByCurrentUser = Random.Shared.Next() % 2 == 0, }); messages.Add(new() { RootMessageId = default, MessageId = "96025b43-5235-44e9-a3fa-98df31edfbfb", User = Faker.GetRandomUser(), MessageType = (MessageType)Random.Shared.Next(0, 4), Title = default, Content = "test immagine", Medias = new() { new() { FileName = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", Url = "https://ihatebeinga.live/media/51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", AltText = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", ContentType = "image/jpg" } }, CreatedAt = DateTime.UtcNow.AddMinutes(Random.Shared.Next(-5000, 0)), IsFavourite = Random.Shared.Next() % 2 == 0, BoostsCounter = Random.Shared.Next(0, 100), IsBoostedByCurrentUser = Random.Shared.Next() % 2 == 0, }); messages.Add(new() { RootMessageId = default, MessageId = "277ca76b-aaad-4aa6-95fb-25f59e2fddf9", User = Faker.GetRandomUser(), MessageType = (MessageType)Random.Shared.Next(0, 4), Title = default, Content = "test audio", Medias = new() { new() { FileName = "09bfb06d0096975f.mp3", Url = "https://cdn.masto.host/mastodonuno/media_attachments/files/107/798/288/501/917/857/original/09bfb06d0096975f.mp3", AltText = "09bfb06d0096975f.mp3", ContentType = "audio/mp3" } }, CreatedAt = DateTime.UtcNow.AddMinutes(Random.Shared.Next(-5000, 0)), IsFavourite = Random.Shared.Next() % 2 == 0, BoostsCounter = Random.Shared.Next(0, 100), IsBoostedByCurrentUser = Random.Shared.Next() % 2 == 0, }); messages.Add(new() { BoostingUser = Faker.GetRandomBoostingUser(), RootMessageId = default, MessageId = "de64e520-a7d3-4f31-b5a9-ba236f3b146c", User = Faker.GetRandomUser(), MessageType = (MessageType)Random.Shared.Next(0, 4), Title = default, Content = "test immagini", Medias = new() { new() { FileName = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", Url = "https://ihatebeinga.live/media/51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", AltText = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", ContentType = "image/jpg" }, new() { FileName = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", Url = "https://ihatebeinga.live/media/51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", AltText = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", ContentType = "image/jpg" }, new() { FileName = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", Url = "https://ihatebeinga.live/media/51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", AltText = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", ContentType = "image/jpg" } }, CreatedAt = DateTime.UtcNow.AddMinutes(Random.Shared.Next(-5000, 0)), IsFavourite = Random.Shared.Next() % 2 == 0, BoostsCounter = Random.Shared.Next(0,100), IsBoostedByCurrentUser = Random.Shared.Next() % 2 == 0, }); messages.Add(new() { RootMessageId = default, MessageId = "de64e520-a7d3-4f31-b5a9-ba236f3b146c", User = Faker.GetRandomUser(), MessageType = (MessageType)Random.Shared.Next(0, 4), Title = default, Content = "test immagini", Medias = new() { new() { FileName = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", Url = "https://ihatebeinga.live/media/51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", AltText = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", ContentType = "image/jpg" }, new() { FileName = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", Url = "https://ihatebeinga.live/media/51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", AltText = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", ContentType = "image/jpg" }, new() { FileName = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", Url = "https://ihatebeinga.live/media/51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", AltText = "51a7cf620f1dd096ac5867d5b78f8c71d57a23972b31c64ec124a8c41e77a618.jpg", ContentType = "image/jpg" } }, CreatedAt = DateTime.UtcNow.AddMinutes(Random.Shared.Next(-5000, 0)), IsFavourite = Random.Shared.Next() % 2 == 0, BoostsCounter = Random.Shared.Next(0,100), IsBoostedByCurrentUser = Random.Shared.Next() % 2 == 0, }); } messages = messages.OrderByDescending(m => m.CreatedAt).ToList(); return messages; } public async ValueTask AddMessages(List messages) { await _db.OpenIndexedDb(); var result = await _db.AddItems(nameof(Message), messages); _logger.LogInformation(result); return result; } public async ValueTask UpdateMessages(List messages) { await _db.OpenIndexedDb(); var result = await _db.UpdateItems(nameof(Message), messages); _logger.LogInformation(result); return result; } public async ValueTask RemoveMessage(string messageId) { await _db.OpenIndexedDb(); var result = await _db.DeleteByKey(nameof(Message), messageId); _logger.LogInformation(result); return result; } #endregion #region Logs public async ValueTask> GetClientLogs() { try { _logger.LogInformation($"opening on {nameof(GetClientLogs)}"); await _db.OpenIndexedDb(); return (await _db.GetAll(nameof(ClientLogs))).OrderByDescending(cl => cl.TimeStamp).ToArray(); } catch (Exception ex) { _logger.LogError(ex, ex.Message); return new List(); } } public async ValueTask AddLog(Exception exception, string where) { try { await _db.OpenIndexedDb(); var maxKey = await _db.GetMaxKey(nameof(ClientLogs)); var minKey = await _db.GetMinKey(nameof(ClientLogs)); if (minKey - maxKey <= -100) for (var i = minKey; i < minKey + 50; i++) _ = await _db.DeleteByKey(nameof(ClientLogs), i); maxKey += 1; var result = await _db.AddItems(nameof(ClientLogs), new() { new() { Id = maxKey, Where = where, Exception = new() { Type = exception.GetType().ToString(), HelpLink = exception.HelpLink, HResult = exception.HResult.ToString(), InnerExceptionMessage = exception.InnerException?.Message, Message = exception.Message, Source = exception.Source, StackTrace = exception.StackTrace, TargetSiteName = exception.TargetSite?.Name } } }); _logger.LogDebug($"{nameof(AddLog)}() add logs result = {result}"); } catch (Exception ex) { _logger.LogError(ex, ex.Message); } } public async ValueTask AddLog(string message, string where) { try { await _db.OpenIndexedDb(); var maxKey = await _db.GetMaxKey(nameof(ClientLogs)); var minKey = await _db.GetMinKey(nameof(ClientLogs)); if (minKey - maxKey <= -100) for (var i = minKey; i < minKey + 50; i++) _ = await _db.DeleteByKey(nameof(ClientLogs), i); maxKey += 1; var result = await _db.AddItems(nameof(ClientLogs), new() { new() { Id = maxKey, Where = where, Exception = null, WarningMessage = message } }); } catch (Exception ex) { _logger.LogError(ex, ex.Message); } } #endregion public async ValueTask RemoveAll(bool includeClientLogs = false) { try { _logger.LogInformation($"opening on {nameof(RemoveAll)}"); await _db.OpenIndexedDb(); _ = await _db.DeleteAll(nameof(Message)); if (includeClientLogs) _ = await _db.DeleteAll(nameof(ClientLogs)); return true; } catch (Exception ex) { _logger.LogError(ex, ex.Message); return default; } } } }