111 lines
3.8 KiB
Go
111 lines
3.8 KiB
Go
package postgres
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
|
|
"telesrv/internal/domain"
|
|
)
|
|
|
|
// registerUserStarGiftMessageRef records an owner-scoped service-message alias
|
|
// for a user-owned gift. Official clients may continue from a freshly emitted
|
|
// messageActionStarGiftUnique or a separate prepaid-upgrade notification and
|
|
// pass that message id to a lifecycle RPC, while payments.getSavedStarGifts may
|
|
// still expose the original received gift message as the aggregate's primary
|
|
// msg_id. expectedUniqueGiftID is zero for an ordinary gift and positive for a
|
|
// unique gift; the write boundary never aliases across lifecycle states.
|
|
func registerUserStarGiftMessageRef(
|
|
ctx context.Context,
|
|
tx pgx.Tx,
|
|
ownerUserID int64,
|
|
msgID int,
|
|
savedGiftID int64,
|
|
uniqueGiftID int64,
|
|
) error {
|
|
return registerViewerStarGiftMessageRef(ctx, tx, ownerUserID, msgID, savedGiftID,
|
|
domain.Peer{Type: domain.PeerTypeUser, ID: ownerUserID}, uniqueGiftID)
|
|
}
|
|
|
|
// registerViewerStarGiftMessageRef binds one viewer-local private message to
|
|
// the aggregate owner explicitly named by the action. The alias does not grant
|
|
// ownership: RPC callers resolve the real owner and authorize it again.
|
|
func registerViewerStarGiftMessageRef(
|
|
ctx context.Context,
|
|
tx pgx.Tx,
|
|
viewerUserID int64,
|
|
msgID int,
|
|
savedGiftID int64,
|
|
expectedOwner domain.Peer,
|
|
uniqueGiftID int64,
|
|
) error {
|
|
if viewerUserID <= 0 || msgID <= 0 || savedGiftID <= 0 || !validLifecyclePeer(expectedOwner) || uniqueGiftID < 0 {
|
|
return fmt.Errorf("register star gift message ref: invalid identity")
|
|
}
|
|
tag, err := tx.Exec(ctx, `
|
|
INSERT INTO star_gift_user_message_refs(owner_user_id,msg_id,saved_gift_id)
|
|
SELECT $1,$2,p.id
|
|
FROM peer_star_gifts p
|
|
WHERE p.id=$3 AND p.owner_peer_type=$4 AND p.owner_peer_id=$5
|
|
AND (($6::bigint=0 AND p.unique_gift_id IS NULL) OR ($6::bigint>0 AND p.unique_gift_id=$6::bigint))
|
|
AND p.lifecycle_status='active'
|
|
ON CONFLICT(owner_user_id,msg_id) DO UPDATE
|
|
SET saved_gift_id=EXCLUDED.saved_gift_id
|
|
WHERE star_gift_user_message_refs.saved_gift_id=EXCLUDED.saved_gift_id`,
|
|
viewerUserID, msgID, savedGiftID, string(expectedOwner.Type), expectedOwner.ID, uniqueGiftID)
|
|
if err != nil {
|
|
return fmt.Errorf("register star gift message ref: %w", err)
|
|
}
|
|
if tag.RowsAffected() != 1 {
|
|
return fmt.Errorf("register star gift message ref: identity collision")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func registerChannelNotificationMessageRef(
|
|
ctx context.Context,
|
|
tx pgx.Tx,
|
|
viewerUserID int64,
|
|
msgID int,
|
|
savedGiftID int64,
|
|
) error {
|
|
if viewerUserID <= 0 || msgID <= 0 || savedGiftID <= 0 {
|
|
return fmt.Errorf("register channel notification star gift message ref: invalid identity")
|
|
}
|
|
tag, err := tx.Exec(ctx, `
|
|
INSERT INTO star_gift_user_message_refs(owner_user_id,msg_id,saved_gift_id)
|
|
SELECT $1,$2,gift.id
|
|
FROM star_gift_channel_notification_jobs job
|
|
JOIN peer_star_gifts gift ON gift.id=job.saved_gift_id
|
|
WHERE job.saved_gift_id=$3 AND job.target_user_id=$1
|
|
AND gift.owner_peer_type='channel' AND gift.lifecycle_status='active'
|
|
ON CONFLICT(owner_user_id,msg_id) DO UPDATE
|
|
SET saved_gift_id=EXCLUDED.saved_gift_id
|
|
WHERE star_gift_user_message_refs.saved_gift_id=EXCLUDED.saved_gift_id`,
|
|
viewerUserID, msgID, savedGiftID)
|
|
if err != nil {
|
|
return fmt.Errorf("register channel notification star gift message ref: %w", err)
|
|
}
|
|
if tag.RowsAffected() != 1 {
|
|
return fmt.Errorf("register channel notification star gift message ref: identity collision")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func userStarGiftMessageRefMatches(
|
|
ctx context.Context,
|
|
db interface {
|
|
QueryRow(context.Context, string, ...any) pgx.Row
|
|
},
|
|
ownerUserID int64,
|
|
msgID int,
|
|
savedGiftID int64,
|
|
) (bool, error) {
|
|
var matches bool
|
|
err := db.QueryRow(ctx, `SELECT EXISTS (
|
|
SELECT 1 FROM star_gift_user_message_refs
|
|
WHERE owner_user_id=$1 AND msg_id=$2 AND saved_gift_id=$3
|
|
)`, ownerUserID, msgID, savedGiftID).Scan(&matches)
|
|
return matches, err
|
|
}
|