174 lines
5.4 KiB
Go
174 lines
5.4 KiB
Go
package broadcast
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"hyapp/pkg/appcode"
|
|
broadcastdomain "hyapp/services/activity-service/internal/domain/broadcast"
|
|
)
|
|
|
|
// ConsumeRedPacketWalletEvent converts one MQ-delivered wallet red-packet fact into IM outbox records.
|
|
func (s *Service) ConsumeRedPacketWalletEvent(ctx context.Context, event broadcastdomain.RedPacketWalletEvent) error {
|
|
if s == nil {
|
|
return nil
|
|
}
|
|
ctx = appcode.WithContext(ctx, event.AppCode)
|
|
switch event.EventType {
|
|
case "WalletRedPacketCreated":
|
|
return s.consumeRedPacketCreated(ctx, event)
|
|
case "WalletRedPacketClaimed":
|
|
if strings.EqualFold(event.Status, "finished") {
|
|
return s.publishRedPacketRoomEvent(ctx, event, "STATUS_CHANGED", event.CreatedAtMS)
|
|
}
|
|
case "WalletRedPacketRefunded":
|
|
return s.publishRedPacketRoomEvent(ctx, event, "STATUS_CHANGED", event.CreatedAtMS)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) ConsumeRedPacketCreatedEvent(ctx context.Context, event broadcastdomain.RedPacketWalletEvent) error {
|
|
if event.EventType == "" {
|
|
event.EventType = "WalletRedPacketCreated"
|
|
}
|
|
return s.ConsumeRedPacketWalletEvent(ctx, event)
|
|
}
|
|
|
|
func (s *Service) consumeRedPacketCreated(ctx context.Context, event broadcastdomain.RedPacketWalletEvent) error {
|
|
if event.RoomID == "" {
|
|
return nil
|
|
}
|
|
enriched, err := s.withRedPacketSenderProfile(ctx, event)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
event = enriched
|
|
if err := s.publishRedPacketRoomEvent(ctx, event, "CREATED", event.CreatedAtMS); err != nil {
|
|
return err
|
|
}
|
|
if strings.EqualFold(event.PacketType, "delayed") && event.RegionID > 0 {
|
|
if _, err := s.PublishRegionBroadcast(ctx, PublishInput{
|
|
EventID: event.EventID + ":region_created",
|
|
BroadcastType: broadcastdomain.TypeRedPacket,
|
|
RegionID: event.RegionID,
|
|
PayloadJSON: redPacketIMPayload(event, "CREATED", "REGION"),
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if strings.EqualFold(event.PacketType, "delayed") && event.OpenAtMS > 0 {
|
|
_, err := s.PublishRoomBroadcast(ctx, event.RoomID, PublishInput{
|
|
EventID: event.EventID + ":open_due",
|
|
BroadcastType: broadcastdomain.TypeRedPacket,
|
|
RegionID: event.RegionID,
|
|
PayloadJSON: redPacketIMPayload(event, "OPEN_DUE", "ROOM"),
|
|
DeliverAtMS: event.OpenAtMS,
|
|
})
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) withRedPacketSenderProfile(ctx context.Context, event broadcastdomain.RedPacketWalletEvent) (broadcastdomain.RedPacketWalletEvent, error) {
|
|
if event.SenderUserID <= 0 || s == nil || s.senderProfileSource == nil {
|
|
return event, nil
|
|
}
|
|
profile, err := s.senderProfileSource.GetSenderProfile(ctx, event.SenderUserID)
|
|
if err != nil {
|
|
return event, err
|
|
}
|
|
if event.SenderAccount == "" {
|
|
event.SenderAccount = profile.Account
|
|
}
|
|
if event.SenderNickname == "" {
|
|
event.SenderNickname = profile.Nickname
|
|
}
|
|
if event.SenderAvatar == "" {
|
|
event.SenderAvatar = profile.Avatar
|
|
}
|
|
if event.RegionCode == "" {
|
|
event.RegionCode = profile.RegionCode
|
|
}
|
|
return event, nil
|
|
}
|
|
|
|
func (s *Service) publishRedPacketRoomEvent(ctx context.Context, event broadcastdomain.RedPacketWalletEvent, eventName string, fallbackDeliverAtMS int64) error {
|
|
if event.RoomID == "" {
|
|
return nil
|
|
}
|
|
_, err := s.PublishRoomBroadcast(ctx, event.RoomID, PublishInput{
|
|
EventID: event.EventID,
|
|
BroadcastType: broadcastdomain.TypeRedPacket,
|
|
RegionID: event.RegionID,
|
|
PayloadJSON: redPacketIMPayload(event, eventName, "ROOM"),
|
|
DeliverAtMS: fallbackDeliverAtMS,
|
|
})
|
|
return err
|
|
}
|
|
|
|
func redPacketIMPayload(event broadcastdomain.RedPacketWalletEvent, eventName string, scope string) string {
|
|
packetMode := "IMMEDIATE"
|
|
if strings.EqualFold(event.PacketType, "delayed") {
|
|
packetMode = "DELAYED"
|
|
}
|
|
status := strings.ToUpper(strings.TrimSpace(event.Status))
|
|
if status == "" {
|
|
status = "ACTIVE"
|
|
}
|
|
payload := map[string]any{
|
|
"type": "ROOM_RED_PACKET",
|
|
"data": map[string]any{
|
|
"event": eventName,
|
|
"scope": scope,
|
|
"packetNo": event.PacketID,
|
|
"packetId": event.PacketID,
|
|
"roomId": event.RoomID,
|
|
"regionId": event.RegionID,
|
|
"regionCode": event.RegionCode,
|
|
"packetMode": packetMode,
|
|
"senderUserId": redPacketUserIDString(event.SenderUserID),
|
|
"actualAccount": redPacketSenderAccount(event),
|
|
"userNickname": event.SenderNickname,
|
|
"userAvatar": event.SenderAvatar,
|
|
"totalAmount": event.TotalAmount,
|
|
"totalCount": event.TotalCount,
|
|
"remainAmount": event.RemainingAmount,
|
|
"remainCount": event.RemainingCount,
|
|
"status": status,
|
|
"delaySeconds": redPacketDelaySeconds(event),
|
|
"refundedAmount": event.RefundedAmount,
|
|
"claimStartTime": event.OpenAtMS,
|
|
"expireTime": event.ExpiresAtMS,
|
|
"serverTime": event.CreatedAtMS,
|
|
},
|
|
}
|
|
encoded, err := json.Marshal(payload)
|
|
if err != nil {
|
|
return `{"type":"ROOM_RED_PACKET","data":{}}`
|
|
}
|
|
return string(encoded)
|
|
}
|
|
|
|
func redPacketUserIDString(userID int64) string {
|
|
if userID <= 0 {
|
|
return ""
|
|
}
|
|
return strconv.FormatInt(userID, 10)
|
|
}
|
|
|
|
func redPacketSenderAccount(event broadcastdomain.RedPacketWalletEvent) string {
|
|
if strings.TrimSpace(event.SenderAccount) != "" {
|
|
return event.SenderAccount
|
|
}
|
|
return redPacketUserIDString(event.SenderUserID)
|
|
}
|
|
|
|
func redPacketDelaySeconds(event broadcastdomain.RedPacketWalletEvent) int64 {
|
|
if !strings.EqualFold(event.PacketType, "delayed") || event.OpenAtMS <= event.CreatedAtMS {
|
|
return 0
|
|
}
|
|
return (event.OpenAtMS - event.CreatedAtMS) / 1000
|
|
}
|