230 lines
7.7 KiB
Go
230 lines
7.7 KiB
Go
package roomadmin
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"hyapp-admin-server/internal/modules/shared"
|
||
)
|
||
|
||
type listQuery struct {
|
||
Page int
|
||
PageSize int
|
||
Keyword string
|
||
OwnerUserID int64
|
||
OwnerUserKeyword string
|
||
OwnerFilter shared.UserIdentityFilter
|
||
Status string
|
||
RegionID int64
|
||
SortBy string
|
||
SortDirection string
|
||
}
|
||
|
||
type roomPinListQuery struct {
|
||
Keyword string
|
||
Page int
|
||
PageSize int
|
||
PinType string
|
||
RegionID int64
|
||
Status string
|
||
}
|
||
|
||
type robotRoomListQuery struct {
|
||
Page int
|
||
PageSize int
|
||
Status string
|
||
}
|
||
|
||
type createRobotRoomRequest struct {
|
||
OwnerRobotUserID flexibleJSONInt64 `json:"ownerRobotUserId"`
|
||
CandidateRobotUserIDs flexibleJSONInt64Slice `json:"candidateRobotUserIds"`
|
||
MinRobotCount int32 `json:"minRobotCount"`
|
||
MaxRobotCount int32 `json:"maxRobotCount"`
|
||
RoomName string `json:"roomName"`
|
||
RoomAvatar string `json:"roomAvatar"`
|
||
VisibleRegionID int64 `json:"visibleRegionId"`
|
||
OwnerCountryCode string `json:"-"`
|
||
SeatCount int32 `json:"seatCount"`
|
||
GiftIDs []string `json:"giftIds"`
|
||
LuckyGiftIDs []string `json:"luckyGiftIds"`
|
||
NormalGiftIntervalMS int64 `json:"normalGiftIntervalMs"`
|
||
LuckyComboMin int64 `json:"luckyComboMin"`
|
||
LuckyComboMax int64 `json:"luckyComboMax"`
|
||
LuckyPauseMinMS int64 `json:"luckyPauseMinMs"`
|
||
LuckyPauseMaxMS int64 `json:"luckyPauseMaxMs"`
|
||
RobotStayMinMS int64 `json:"robotStayMinMs"`
|
||
RobotStayMaxMS int64 `json:"robotStayMaxMs"`
|
||
RobotReplaceMinMS int64 `json:"robotReplaceMinMs"`
|
||
RobotReplaceMaxMS int64 `json:"robotReplaceMaxMs"`
|
||
MaxGiftSenders int64 `json:"maxGiftSenders"`
|
||
}
|
||
|
||
type flexibleJSONInt64 int64
|
||
|
||
type flexibleJSONInt64Slice []int64
|
||
|
||
func (v *flexibleJSONInt64) UnmarshalJSON(data []byte) error {
|
||
// 机器人用户 ID 来自 int64,前端必须按字符串提交才能避开 JS 安全整数上限;这里同时兼容旧脚本传数字。
|
||
value, err := parseFlexibleJSONInt64(data)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
*v = flexibleJSONInt64(value)
|
||
return nil
|
||
}
|
||
|
||
func (values *flexibleJSONInt64Slice) UnmarshalJSON(data []byte) error {
|
||
// JSON 数组逐项走同一套 int64 解析,避免候选机器人列表里混入浮点或科学计数法。
|
||
var raw []json.RawMessage
|
||
if err := json.Unmarshal(data, &raw); err != nil {
|
||
return err
|
||
}
|
||
out := make([]int64, 0, len(raw))
|
||
for _, item := range raw {
|
||
value, err := parseFlexibleJSONInt64(item)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
out = append(out, value)
|
||
}
|
||
*values = out
|
||
return nil
|
||
}
|
||
|
||
func parseFlexibleJSONInt64(data []byte) (int64, error) {
|
||
raw := strings.TrimSpace(string(data))
|
||
if raw == "" || raw == "null" {
|
||
return 0, nil
|
||
}
|
||
if strings.HasPrefix(raw, "\"") {
|
||
var text string
|
||
if err := json.Unmarshal(data, &text); err != nil {
|
||
return 0, err
|
||
}
|
||
raw = strings.TrimSpace(text)
|
||
}
|
||
if raw == "" {
|
||
return 0, nil
|
||
}
|
||
if strings.ContainsAny(raw, ".eE") {
|
||
// ID 没有小数语义,拒绝 float/scientific notation,避免 18 位 ID 被中间层改写精度。
|
||
return 0, fmt.Errorf("integer id must not be decimal")
|
||
}
|
||
return strconv.ParseInt(raw, 10, 64)
|
||
}
|
||
|
||
type createRoomPinRequest struct {
|
||
DurationDays int64 `json:"durationDays"`
|
||
ExpiresAtMS int64 `json:"expiresAtMs"`
|
||
PinType string `json:"pinType"`
|
||
PinnedAtMS int64 `json:"pinnedAtMs"`
|
||
RoomID string `json:"roomId"`
|
||
Weight int64 `json:"weight"`
|
||
}
|
||
|
||
type updateRoomRequest struct {
|
||
CoverURL *string `json:"coverUrl"`
|
||
CloseReason *string `json:"closeReason"`
|
||
Description *string `json:"description"`
|
||
Mode *string `json:"mode"`
|
||
Status *string `json:"status"`
|
||
Title *string `json:"title"`
|
||
VisibleRegionID *int64 `json:"visibleRegionId"`
|
||
}
|
||
|
||
type updateRoomConfigRequest struct {
|
||
AllowedSeatCounts []int32 `json:"allowedSeatCounts"`
|
||
DefaultSeatCount int32 `json:"defaultSeatCount"`
|
||
}
|
||
|
||
type updateRoomWhitelistRequest struct {
|
||
UserIDs flexibleJSONInt64StringSlice `json:"userIds"`
|
||
}
|
||
|
||
type updateHumanRoomRobotConfigRequest struct {
|
||
Enabled bool `json:"enabled"`
|
||
CandidateRoomMaxOnline int32 `json:"candidateRoomMaxOnline"`
|
||
RoomFullStopOnline int32 `json:"roomFullStopOnline"`
|
||
RoomTargetMinOnline int32 `json:"roomTargetMinOnline"`
|
||
RoomTargetMaxOnline int32 `json:"roomTargetMaxOnline"`
|
||
RobotStayMinMS int64 `json:"robotStayMinMs"`
|
||
RobotStayMaxMS int64 `json:"robotStayMaxMs"`
|
||
RobotReplaceMinMS int64 `json:"robotReplaceMinMs"`
|
||
RobotReplaceMaxMS int64 `json:"robotReplaceMaxMs"`
|
||
NormalGiftIntervalMS int64 `json:"normalGiftIntervalMs"`
|
||
NormalGiftIntervalMinMS int64 `json:"normalGiftIntervalMinMs"`
|
||
NormalGiftIntervalMaxMS int64 `json:"normalGiftIntervalMaxMs"`
|
||
GiftIDs []string `json:"giftIds"`
|
||
LuckyGiftIDs []string `json:"luckyGiftIds"`
|
||
SuperLuckyGiftIDs []string `json:"superLuckyGiftIds"`
|
||
LuckyComboMin int64 `json:"luckyComboMin"`
|
||
LuckyComboMax int64 `json:"luckyComboMax"`
|
||
LuckyPauseMinMS int64 `json:"luckyPauseMinMs"`
|
||
LuckyPauseMaxMS int64 `json:"luckyPauseMaxMs"`
|
||
MaxGiftSenders int64 `json:"maxGiftSenders"`
|
||
AllowedOwnerIDs flexibleCommaStringList `json:"allowedOwnerIds"`
|
||
CountryLimitEnabled bool `json:"countryLimitEnabled"`
|
||
CountryRules []HumanRoomRobotCountryRule `json:"countryRules"`
|
||
}
|
||
|
||
type flexibleJSONInt64StringSlice []string
|
||
|
||
func (values *flexibleJSONInt64StringSlice) UnmarshalJSON(data []byte) error {
|
||
// 房间白名单 user_id 是 int64 标识,API 合约统一按字符串输出;这里兼容旧脚本传数字但拒绝小数。
|
||
var raw []json.RawMessage
|
||
if err := json.Unmarshal(data, &raw); err != nil {
|
||
return err
|
||
}
|
||
out := make([]string, 0, len(raw))
|
||
for _, item := range raw {
|
||
value, err := parseFlexibleJSONInt64(item)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if value > 0 {
|
||
out = append(out, strconv.FormatInt(value, 10))
|
||
}
|
||
}
|
||
*values = out
|
||
return nil
|
||
}
|
||
|
||
type flexibleCommaStringList []string
|
||
|
||
func (values *flexibleCommaStringList) UnmarshalJSON(data []byte) error {
|
||
// 真人房机器人后台是人工输入框场景,兼容 "1001,1002" 和 ["1001","1002"] 两种提交,统一在 service 层去空去重。
|
||
raw := strings.TrimSpace(string(data))
|
||
if raw == "" || raw == "null" {
|
||
*values = nil
|
||
return nil
|
||
}
|
||
if strings.HasPrefix(raw, "\"") {
|
||
var text string
|
||
if err := json.Unmarshal(data, &text); err != nil {
|
||
return err
|
||
}
|
||
*values = splitCommaStringList(text)
|
||
return nil
|
||
}
|
||
var list []string
|
||
if err := json.Unmarshal(data, &list); err != nil {
|
||
return err
|
||
}
|
||
*values = splitCommaStringList(strings.Join(list, ","))
|
||
return nil
|
||
}
|
||
|
||
func splitCommaStringList(raw string) []string {
|
||
parts := strings.Split(raw, ",")
|
||
out := make([]string, 0, len(parts))
|
||
for _, part := range parts {
|
||
part = strings.TrimSpace(part)
|
||
if part != "" {
|
||
out = append(out, part)
|
||
}
|
||
}
|
||
return out
|
||
}
|