fix: sync StarGift private message references

This commit is contained in:
A 2026-07-21 15:45:16 +08:00
parent 1a2d03f529
commit 30774f8c39
12 changed files with 580 additions and 15 deletions

View file

@ -117,8 +117,19 @@ func (s *MessageStore) SendPrivateText(ctx context.Context, req domain.SendPriva
}
type privateSendTxHooks struct {
before func(context.Context, pgx.Tx, *domain.SendPrivateTextRequest) error
after func(context.Context, pgx.Tx, domain.SendPrivateTextResult) error
before func(context.Context, pgx.Tx, *domain.SendPrivateTextRequest) error
projectMedia func(context.Context, pgx.Tx, *domain.SendPrivateTextRequest) (privateSendMediaProjection, error)
after func(context.Context, pgx.Tx, domain.SendPrivateTextResult) error
}
// privateSendMediaProjection separates the logical private-message payload
// from the two account-local message-box projections. Most messages use the
// same media for all three fields. Service actions that carry message ids must
// project those ids per account because box ids are not shared by both users.
type privateSendMediaProjection struct {
Shared *domain.MessageMedia
Sender *domain.MessageMedia
Recipient *domain.MessageMedia
}
func (s *MessageStore) sendPrivateTextWithHooks(ctx context.Context, req domain.SendPrivateTextRequest, hooks privateSendTxHooks) (res domain.SendPrivateTextResult, err error) {
@ -228,7 +239,22 @@ func (s *MessageStore) sendPrivateTextOnce(ctx context.Context, req domain.SendP
return domain.SendPrivateTextResult{}, err
}
}
mediaJSON, err := encodeMessageMedia(req.Media)
media := privateSendMediaProjection{Shared: req.Media, Sender: req.Media, Recipient: req.Media}
if hooks.projectMedia != nil {
media, err = hooks.projectMedia(ctx, tx, &req)
if err != nil {
return domain.SendPrivateTextResult{}, err
}
}
sharedMediaJSON, err := encodeMessageMedia(media.Shared)
if err != nil {
return domain.SendPrivateTextResult{}, err
}
senderMediaJSON, err := encodeMessageMedia(media.Sender)
if err != nil {
return domain.SendPrivateTextResult{}, err
}
recipientMediaJSON, err := encodeMessageMedia(media.Recipient)
if err != nil {
return domain.SendPrivateTextResult{}, err
}
@ -255,7 +281,7 @@ func (s *MessageStore) sendPrivateTextOnce(ctx context.Context, req domain.SendP
TtlPeriod: int32(ttlPeriod),
ExpiresAt: int32(expiresAt),
EntitiesJson: entities,
MediaJson: mediaJSON,
MediaJson: sharedMediaJSON,
ReplyMarkupJson: replyMarkupJSON,
RichMessageJson: richMessageJSON,
ViaBotID: req.ViaBotID,
@ -315,7 +341,7 @@ func (s *MessageStore) sendPrivateTextOnce(ctx context.Context, req domain.SendP
ExpiresAt: int32(expiresAt),
EntitiesJson: entities,
Pts: int32(senderPts),
MediaJson: mediaJSON,
MediaJson: senderMediaJSON,
ReplyMarkupJson: replyMarkupJSON,
RichMessageJson: richMessageJSON,
ViaBotID: req.ViaBotID,
@ -323,7 +349,7 @@ func (s *MessageStore) sendPrivateTextOnce(ctx context.Context, req domain.SendP
Effect: req.Effect,
// voice/round 在发送者自己的副本上也保持"未听",直到对端
// readMessageContents 触发 sender 侧清除;发给自己无人可听,恒已读。
MediaUnread: req.Media.HasUnreadPayload() && !selfMessage,
MediaUnread: media.Sender.HasUnreadPayload() && !selfMessage,
ReactionUnread: false,
}
applyCreateMessageBoxMetadata(&senderArg, senderMeta)
@ -334,7 +360,7 @@ func (s *MessageStore) sendPrivateTextOnce(ctx context.Context, req domain.SendP
sender := messageFromBoxRow(senderRow)
sender.RandomID = req.RandomID
// 共享媒体索引(0118):发送者侧 box 按媒体类别建索引(peer=收件人)。
if err := insertMessageBoxMediaIndexTx(ctx, tx, req.SenderUserID, req.RecipientUserID, int(senderBoxID), req.Date, req.Media, req.Entities); err != nil {
if err := insertMessageBoxMediaIndexTx(ctx, tx, req.SenderUserID, req.RecipientUserID, int(senderBoxID), req.Date, media.Sender, req.Entities); err != nil {
return domain.SendPrivateTextResult{}, err
}
if err := qtx.UpsertOutboxDialog(ctx, sqlcgen.UpsertOutboxDialogParams{
@ -388,13 +414,13 @@ func (s *MessageStore) sendPrivateTextOnce(ctx context.Context, req domain.SendP
ExpiresAt: int32(expiresAt),
EntitiesJson: entities,
Pts: int32(recipientPts),
MediaJson: mediaJSON,
MediaJson: recipientMediaJSON,
ReplyMarkupJson: replyMarkupJSON,
RichMessageJson: richMessageJSON,
ViaBotID: req.ViaBotID,
GroupedID: req.GroupedID,
Effect: req.Effect,
MediaUnread: req.Media.HasUnreadPayload(),
MediaUnread: media.Recipient.HasUnreadPayload(),
ReactionUnread: false,
}
applyCreateMessageBoxMetadata(&recipientArg, recipientMeta)
@ -405,7 +431,7 @@ func (s *MessageStore) sendPrivateTextOnce(ctx context.Context, req domain.SendP
recipient = messageFromBoxRow(recipientRow)
recipient.RandomID = req.RandomID
// 共享媒体索引(0118):收件人侧 box 按媒体类别建索引(peer=发送者)。
if err := insertMessageBoxMediaIndexTx(ctx, tx, req.RecipientUserID, req.SenderUserID, int(recipientBoxID), req.Date, req.Media, req.Entities); err != nil {
if err := insertMessageBoxMediaIndexTx(ctx, tx, req.RecipientUserID, req.SenderUserID, int(recipientBoxID), req.Date, media.Recipient, req.Entities); err != nil {
return domain.SendPrivateTextResult{}, err
}
if err := qtx.UpsertInboxDialog(ctx, sqlcgen.UpsertInboxDialogParams{