Fix MAX emoji attachments
This commit is contained in:
@@ -160,9 +160,12 @@ static async Task EnsureCompatibilitySchemaAsync(QMaxDbContext db)
|
||||
await db.Database.ExecuteSqlRawAsync("ALTER TABLE MessageAttachments ADD COLUMN ExternalId TEXT;");
|
||||
}
|
||||
|
||||
await RemoveDuplicateMessageAttachmentsAsync(db);
|
||||
await db.Database.ExecuteSqlRawAsync("DROP INDEX IF EXISTS IX_MessageAttachments_MessageId_ExternalId;");
|
||||
await db.Database.ExecuteSqlRawAsync("""
|
||||
CREATE INDEX IF NOT EXISTS IX_MessageAttachments_MessageId_ExternalId
|
||||
ON MessageAttachments (MessageId, ExternalId);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS IX_MessageAttachments_MessageId_ExternalId
|
||||
ON MessageAttachments (MessageId, ExternalId)
|
||||
WHERE ExternalId IS NOT NULL AND ExternalId <> '';
|
||||
""");
|
||||
|
||||
await db.Database.ExecuteSqlRawAsync("""
|
||||
@@ -189,6 +192,29 @@ static async Task EnsureCompatibilitySchemaAsync(QMaxDbContext db)
|
||||
await RemoveGenericMediaLabelsAsync(db);
|
||||
}
|
||||
|
||||
static async Task RemoveDuplicateMessageAttachmentsAsync(QMaxDbContext db)
|
||||
{
|
||||
var attachments = await db.MessageAttachments
|
||||
.Where(attachment => attachment.ExternalId != null && attachment.ExternalId != "")
|
||||
.ToListAsync();
|
||||
|
||||
var duplicates = attachments
|
||||
.OrderBy(attachment => attachment.MessageId)
|
||||
.ThenBy(attachment => attachment.ExternalId)
|
||||
.ThenByDescending(attachment => attachment.FileSizeBytes)
|
||||
.ThenBy(attachment => attachment.CreatedAt)
|
||||
.GroupBy(attachment => new { attachment.MessageId, attachment.ExternalId })
|
||||
.SelectMany(group => group.Skip(1))
|
||||
.ToList();
|
||||
if (duplicates.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
db.MessageAttachments.RemoveRange(duplicates);
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
static async Task RemoveGenericMediaLabelsAsync(QMaxDbContext db)
|
||||
{
|
||||
var placeholderMessages = await db.Messages
|
||||
|
||||
@@ -194,7 +194,7 @@ public sealed class MaxBridgeSyncService(
|
||||
DeliveryState = ResolveDeliveryState(incoming)
|
||||
};
|
||||
|
||||
foreach (var incomingAttachment in incoming.Attachments ?? [])
|
||||
foreach (var incomingAttachment in DistinctAttachments(incoming.Attachments ?? []))
|
||||
{
|
||||
var attachment = await CreateAttachmentAsync(incomingAttachment, maxBridgeClient, storage, cancellationToken);
|
||||
message.Attachments.Add(attachment);
|
||||
@@ -481,7 +481,7 @@ public sealed class MaxBridgeSyncService(
|
||||
var metadataChanged = false;
|
||||
var addedAttachments = new List<MessageAttachment>();
|
||||
var knownAttachments = message.Attachments.ToList();
|
||||
var incomingAttachments = incoming.Attachments ?? [];
|
||||
var incomingAttachments = DistinctAttachments(incoming.Attachments ?? []);
|
||||
var cleanText = MessageTextSanitizer.CleanMessageText(
|
||||
incoming.Text,
|
||||
incomingAttachments.Count > 0 || message.Attachments.Count > 0);
|
||||
@@ -564,6 +564,41 @@ public sealed class MaxBridgeSyncService(
|
||||
return new MessageMergeResult(changed, addedAttachments);
|
||||
}
|
||||
|
||||
private static IReadOnlyList<MaxAttachmentUpdate> DistinctAttachments(IReadOnlyList<MaxAttachmentUpdate> attachments)
|
||||
{
|
||||
if (attachments.Count <= 1)
|
||||
{
|
||||
return attachments;
|
||||
}
|
||||
|
||||
var seen = new HashSet<string>(StringComparer.Ordinal);
|
||||
var result = new List<MaxAttachmentUpdate>(attachments.Count);
|
||||
foreach (var attachment in attachments)
|
||||
{
|
||||
if (seen.Add(AttachmentIdentity(attachment)))
|
||||
{
|
||||
result.Add(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string AttachmentIdentity(MaxAttachmentUpdate attachment)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(attachment.ExternalId))
|
||||
{
|
||||
return $"external:{attachment.ExternalId}";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(attachment.RemoteUrl))
|
||||
{
|
||||
return $"remote:{attachment.RemoteUrl}";
|
||||
}
|
||||
|
||||
return $"fallback:{attachment.Kind}:{attachment.FileName}:{attachment.SortOrder}:{attachment.TextContent?.Length ?? 0}";
|
||||
}
|
||||
|
||||
private static async Task<MessageAttachment> CreateAttachmentAsync(
|
||||
MaxAttachmentUpdate incoming,
|
||||
IMaxBridgeClient maxBridgeClient,
|
||||
|
||||
Reference in New Issue
Block a user