package service import ( "strconv" "strings" roomv1 "hyapp.local/api/proto/room/v1" "hyapp/services/room-service/internal/room/command" "hyapp/services/room-service/internal/room/state" ) func normalizeGiftTargetUserIDs(targetUserID int64, targetUserIDs []int64) []int64 { seen := make(map[int64]bool, len(targetUserIDs)+1) ids := make([]int64, 0, len(targetUserIDs)+1) for _, userID := range targetUserIDs { if userID <= 0 || seen[userID] { continue } seen[userID] = true ids = append(ids, userID) } if len(ids) == 0 && targetUserID > 0 { ids = append(ids, targetUserID) } return ids } func giftTargetHostScopesFromProto(scopes []*roomv1.SendGiftTargetHostScope) []command.GiftTargetHostScope { result := make([]command.GiftTargetHostScope, 0, len(scopes)) seen := make(map[int64]bool, len(scopes)) for _, scope := range scopes { targetUserID := scope.GetTargetUserId() if targetUserID <= 0 || seen[targetUserID] { continue } seen[targetUserID] = true result = append(result, command.GiftTargetHostScope{ TargetUserID: targetUserID, TargetIsHost: scope.GetTargetIsHost(), TargetHostRegionID: scope.GetTargetHostRegionId(), TargetAgencyOwnerUserID: scope.GetTargetAgencyOwnerUserId(), }) } return result } func giftDisplayProfileFromProto(item *roomv1.SendGiftDisplayProfile) command.GiftDisplayProfile { if item == nil || item.GetUserId() <= 0 { return command.GiftDisplayProfile{} } // 展示快照只裁剪空白字符,不做业务兜底;兜底顺序统一放在 giftDisplayName,避免事件字段互相不一致。 return command.GiftDisplayProfile{ UserID: item.GetUserId(), Username: strings.TrimSpace(item.GetUsername()), Avatar: strings.TrimSpace(item.GetAvatar()), DisplayUserID: strings.TrimSpace(item.GetDisplayUserId()), PrettyDisplayUserID: strings.TrimSpace(item.GetPrettyDisplayUserId()), } } func giftDisplayProfilesFromProto(items []*roomv1.SendGiftDisplayProfile) []command.GiftDisplayProfile { result := make([]command.GiftDisplayProfile, 0, len(items)) seen := make(map[int64]bool, len(items)) for _, item := range items { profile := giftDisplayProfileFromProto(item) if profile.UserID <= 0 || seen[profile.UserID] { continue } seen[profile.UserID] = true result = append(result, profile) } return result } func giftDisplayProfileForUser(profiles []command.GiftDisplayProfile, userID int64) command.GiftDisplayProfile { if userID <= 0 { return command.GiftDisplayProfile{} } for _, profile := range profiles { if profile.UserID == userID { return profile } } return command.GiftDisplayProfile{UserID: userID} } func giftDisplayName(profile command.GiftDisplayProfile) string { // Flutter 的 IM 解析已支持 sender_name/receiver_nickname;这里按用户昵称、靓号、短号依次兜底,避免跨房飘窗直接落到 User 。 for _, value := range []string{profile.Username, profile.PrettyDisplayUserID, profile.DisplayUserID} { if trimmed := strings.TrimSpace(value); trimmed != "" { return trimmed } } return "" } func giftTargetUserIDsAttribute(targetUserIDs []int64) string { if len(targetUserIDs) == 0 { return "" } parts := make([]string, 0, len(targetUserIDs)) for _, targetUserID := range targetUserIDs { parts = append(parts, strconv.FormatInt(targetUserID, 10)) } return strings.Join(parts, ",") } func findRankItem(items []state.RankItem, userID int64) state.RankItem { // 送礼后通常能找到发送方榜单项;找不到时返回 user_id 占位避免空事件。 for _, item := range items { if item.UserID == userID { return item } } return state.RankItem{UserID: userID} }