155 lines
6.3 KiB
C#
155 lines
6.3 KiB
C#
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 MergeOutgoingRemoteAttachmentEchoesAsync(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.OutgoingAttachmentEchoMerges;");
|
|
await db.Database.ExecuteSqlRawAsync("""
|
|
CREATE TEMP TABLE OutgoingAttachmentEchoMerges (
|
|
LocalId TEXT NOT NULL PRIMARY KEY,
|
|
RemoteId TEXT NOT NULL,
|
|
ExternalId TEXT NULL,
|
|
RemoteUrl TEXT NULL
|
|
);
|
|
""");
|
|
await db.Database.ExecuteSqlRawAsync("""
|
|
INSERT OR IGNORE INTO OutgoingAttachmentEchoMerges (LocalId, RemoteId, ExternalId, RemoteUrl)
|
|
SELECT localAttachment.Id,
|
|
remoteAttachment.Id,
|
|
remoteAttachment.ExternalId,
|
|
remoteAttachment.RemoteUrl
|
|
FROM Messages AS message
|
|
INNER JOIN MessageAttachments AS localAttachment ON localAttachment.MessageId = message.Id
|
|
INNER JOIN MessageAttachments AS remoteAttachment ON remoteAttachment.MessageId = message.Id
|
|
WHERE message.Direction = 'Outgoing'
|
|
AND localAttachment.Id <> remoteAttachment.Id
|
|
AND localAttachment.SortOrder = remoteAttachment.SortOrder
|
|
AND localAttachment.Kind = remoteAttachment.Kind
|
|
AND (localAttachment.ExternalId IS NULL OR trim(localAttachment.ExternalId) = '')
|
|
AND (localAttachment.RemoteUrl IS NULL OR trim(localAttachment.RemoteUrl) = '')
|
|
AND localAttachment.StorageFileName NOT LIKE 'remote-%'
|
|
AND (
|
|
(remoteAttachment.ExternalId IS NOT NULL AND trim(remoteAttachment.ExternalId) <> '') OR
|
|
(remoteAttachment.RemoteUrl IS NOT NULL AND trim(remoteAttachment.RemoteUrl) <> '') OR
|
|
remoteAttachment.StorageFileName LIKE 'remote-%'
|
|
);
|
|
""");
|
|
await db.Database.ExecuteSqlRawAsync("""
|
|
DELETE FROM MessageAttachments
|
|
WHERE Id IN (SELECT RemoteId FROM OutgoingAttachmentEchoMerges);
|
|
""");
|
|
await db.Database.ExecuteSqlRawAsync("""
|
|
UPDATE MessageAttachments
|
|
SET ExternalId = COALESCE(NULLIF(ExternalId, ''), (
|
|
SELECT ExternalId
|
|
FROM OutgoingAttachmentEchoMerges
|
|
WHERE LocalId = MessageAttachments.Id
|
|
)),
|
|
RemoteUrl = COALESCE(NULLIF(RemoteUrl, ''), (
|
|
SELECT RemoteUrl
|
|
FROM OutgoingAttachmentEchoMerges
|
|
WHERE LocalId = MessageAttachments.Id
|
|
))
|
|
WHERE Id IN (SELECT LocalId FROM OutgoingAttachmentEchoMerges);
|
|
""");
|
|
await db.Database.ExecuteSqlRawAsync("DROP TABLE IF EXISTS temp.OutgoingAttachmentEchoMerges;");
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
|
|
}
|