using Microsoft.EntityFrameworkCore; using QMax.Api.Data.Entities; namespace QMax.Api.Data; public static class QMaxDatabaseCleanup { public static async Task RemoveLegacyWebFileAttachmentEchoesAsync(QMaxDbContext db) { var connection = db.Database.GetDbConnection(); if (connection.State != System.Data.ConnectionState.Open) { await connection.OpenAsync(); } await db.Database.ExecuteSqlRawAsync("DROP TABLE IF EXISTS temp.LegacyWebFileMessageIds;"); await db.Database.ExecuteSqlRawAsync(""" CREATE TEMP TABLE LegacyWebFileMessageIds ( Id TEXT NOT NULL PRIMARY KEY ); """); await db.Database.ExecuteSqlRawAsync(""" INSERT OR IGNORE INTO LegacyWebFileMessageIds (Id) SELECT DISTINCT legacy.Id FROM Messages AS legacy INNER JOIN MessageAttachments AS legacyAttachment ON legacyAttachment.MessageId = legacy.Id WHERE legacy.Direction = 'Outgoing' AND legacy.ExternalId LIKE 'web-file-%' AND legacyAttachment.Sha256 IS NOT NULL AND legacyAttachment.Sha256 <> '' AND EXISTS ( SELECT 1 FROM Messages AS confirmed INNER JOIN MessageAttachments AS confirmedAttachment ON confirmedAttachment.MessageId = confirmed.Id WHERE confirmed.ChatId = legacy.ChatId AND confirmed.Id <> legacy.Id AND confirmed.Direction = 'Outgoing' AND confirmed.ExternalId IS NOT NULL AND confirmed.ExternalId NOT LIKE 'web-file-%' AND confirmedAttachment.Sha256 = legacyAttachment.Sha256 ); """); await db.Database.ExecuteSqlRawAsync(""" DELETE FROM MessageAttachments WHERE MessageId IN (SELECT Id FROM LegacyWebFileMessageIds); """); await db.Database.ExecuteSqlRawAsync(""" DELETE FROM Messages WHERE Id IN (SELECT Id FROM LegacyWebFileMessageIds); """); await db.Database.ExecuteSqlRawAsync("DROP TABLE IF EXISTS temp.LegacyWebFileMessageIds;"); } public static async Task ClearUnreadCountsForLatestOutgoingChatsAsync(QMaxDbContext db) { var unreadChats = await db.Chats .Where(chat => chat.UnreadCount > 0) .ToListAsync(); if (unreadChats.Count == 0) { return; } var changed = false; foreach (var chat in unreadChats) { var chatMessages = await db.Messages .Where(message => message.ChatId == chat.Id && message.DeletedAt == null) .Select(message => new { message.Direction, message.SentAt, message.Id }) .ToListAsync(); var latestMessage = chatMessages .OrderByDescending(message => message.SentAt) .ThenByDescending(message => message.Id) .FirstOrDefault(); if (latestMessage?.Direction != MessageDirection.Outgoing) { continue; } chat.UnreadCount = 0; chat.UpdatedAt = DateTimeOffset.UtcNow; changed = true; } if (changed) { await db.SaveChangesAsync(); } } }