Store MAX chat URLs for direct opens
This commit is contained in:
@@ -32,7 +32,7 @@ public sealed class MaxBridgeSyncService(
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<int> SyncChatHistoryAsync(string externalChatId, CancellationToken cancellationToken)
|
||||
public async Task<int> SyncChatHistoryAsync(string externalChatId, string? chatUrl, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(externalChatId))
|
||||
{
|
||||
@@ -41,7 +41,7 @@ public sealed class MaxBridgeSyncService(
|
||||
|
||||
try
|
||||
{
|
||||
var update = await maxBridgeClient.FetchChatHistoryAsync(externalChatId, cancellationToken);
|
||||
var update = await maxBridgeClient.FetchChatHistoryAsync(externalChatId, chatUrl, cancellationToken);
|
||||
return update is null
|
||||
? 0
|
||||
: await ApplyUpdatesAsync([update], incrementUnread: false, sendPushNotifications: false, cancellationToken);
|
||||
@@ -77,10 +77,16 @@ public sealed class MaxBridgeSyncService(
|
||||
|
||||
foreach (var update in updates)
|
||||
{
|
||||
var nextWebUrl = CleanWebUrl(update.ChatUrl);
|
||||
if (!trackedChatsByExternalId.TryGetValue(update.ExternalId, out var chat))
|
||||
{
|
||||
chat = await db.Chats
|
||||
.FirstOrDefaultAsync(x => x.ExternalId == update.ExternalId, cancellationToken);
|
||||
if (chat is null && !string.IsNullOrWhiteSpace(nextWebUrl))
|
||||
{
|
||||
chat = await db.Chats
|
||||
.FirstOrDefaultAsync(x => x.WebUrl == nextWebUrl, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
var chatWasCreated = chat is null;
|
||||
@@ -91,6 +97,7 @@ public sealed class MaxBridgeSyncService(
|
||||
ExternalId = update.ExternalId,
|
||||
Title = update.Title,
|
||||
AvatarUrl = update.AvatarUrl,
|
||||
WebUrl = nextWebUrl,
|
||||
Kind = ChatKind.MaxDialog
|
||||
};
|
||||
db.Chats.Add(chat);
|
||||
@@ -102,6 +109,7 @@ public sealed class MaxBridgeSyncService(
|
||||
var nextAvatarUrl = string.IsNullOrWhiteSpace(update.AvatarUrl)
|
||||
? chat.AvatarUrl
|
||||
: update.AvatarUrl;
|
||||
nextWebUrl ??= chat.WebUrl;
|
||||
var metadataChanged = false;
|
||||
if (!string.Equals(chat.ExternalId, update.ExternalId, StringComparison.Ordinal))
|
||||
{
|
||||
@@ -121,6 +129,12 @@ public sealed class MaxBridgeSyncService(
|
||||
metadataChanged = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(chat.WebUrl, nextWebUrl, StringComparison.Ordinal))
|
||||
{
|
||||
chat.WebUrl = nextWebUrl;
|
||||
metadataChanged = true;
|
||||
}
|
||||
|
||||
if (metadataChanged)
|
||||
{
|
||||
chat.UpdatedAt = DateTimeOffset.UtcNow;
|
||||
@@ -965,6 +979,12 @@ public sealed class MaxBridgeSyncService(
|
||||
: MessageDeliveryState.Sent;
|
||||
}
|
||||
|
||||
private static string? CleanWebUrl(string? value)
|
||||
{
|
||||
var trimmed = value?.Trim();
|
||||
return string.IsNullOrWhiteSpace(trimmed) ? null : trimmed;
|
||||
}
|
||||
|
||||
private static string? LastMessagePreview(string? text, IEnumerable<MessageAttachment> attachments)
|
||||
{
|
||||
var orderedAttachments = attachments.OrderBy(x => x.SortOrder).ToArray();
|
||||
|
||||
@@ -59,7 +59,7 @@ public sealed class MaxOutboxService(
|
||||
MaxSendResult result;
|
||||
try
|
||||
{
|
||||
result = await SendToMaxAsync(chat.ExternalId, message, cancellationToken);
|
||||
result = await SendToMaxAsync(chat, message, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -74,6 +74,12 @@ public sealed class MaxOutboxService(
|
||||
: result.ExternalMessageId;
|
||||
message.DeliveryState = MessageDeliveryState.Sent;
|
||||
message.Error = null;
|
||||
if (!string.IsNullOrWhiteSpace(result.ChatUrl) &&
|
||||
!string.Equals(chat.WebUrl, result.ChatUrl, StringComparison.Ordinal))
|
||||
{
|
||||
chat.WebUrl = result.ChatUrl;
|
||||
chat.UpdatedAt = DateTimeOffset.UtcNow;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -86,14 +92,16 @@ public sealed class MaxOutboxService(
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<MaxSendResult> SendToMaxAsync(string externalChatId, Message message, CancellationToken cancellationToken)
|
||||
private async Task<MaxSendResult> SendToMaxAsync(Chat chat, Message message, CancellationToken cancellationToken)
|
||||
{
|
||||
var externalChatId = chat.ExternalId!;
|
||||
var chatUrl = chat.WebUrl;
|
||||
var attachments = message.Attachments.OrderBy(attachment => attachment.SortOrder).ToArray();
|
||||
if (attachments.Length == 0)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(message.Text)
|
||||
? new MaxSendResult(false, null, "Text is empty.")
|
||||
: await maxBridge.SendTextAsync(externalChatId, message.Text, cancellationToken);
|
||||
: await maxBridge.SendTextAsync(externalChatId, chatUrl, message.Text, cancellationToken);
|
||||
}
|
||||
|
||||
MaxSendResult? lastResult = null;
|
||||
@@ -108,7 +116,11 @@ public sealed class MaxOutboxService(
|
||||
}
|
||||
|
||||
var caption = attachment.SortOrder == 0 ? message.Text ?? "" : "";
|
||||
var result = await maxBridge.SendAttachmentAsync(externalChatId, path, caption, cancellationToken);
|
||||
var result = await maxBridge.SendAttachmentAsync(externalChatId, chatUrl, path, caption, cancellationToken);
|
||||
if (!string.IsNullOrWhiteSpace(result.ChatUrl))
|
||||
{
|
||||
chatUrl = result.ChatUrl;
|
||||
}
|
||||
lastResult = result;
|
||||
if (!result.Success && !string.IsNullOrWhiteSpace(result.Error))
|
||||
{
|
||||
@@ -117,8 +129,8 @@ public sealed class MaxOutboxService(
|
||||
}
|
||||
|
||||
return errors.Count == 0
|
||||
? new MaxSendResult(true, lastResult?.ExternalMessageId, null)
|
||||
: new MaxSendResult(false, lastResult?.ExternalMessageId, string.Join("; ", errors.Distinct()));
|
||||
? new MaxSendResult(true, lastResult?.ExternalMessageId, null, chatUrl)
|
||||
: new MaxSendResult(false, lastResult?.ExternalMessageId, string.Join("; ", errors.Distinct()), chatUrl);
|
||||
}
|
||||
|
||||
private async Task MarkFailedAsync(Message message, string error, CancellationToken cancellationToken)
|
||||
|
||||
Reference in New Issue
Block a user