292 lines
8.0 KiB
Go
292 lines
8.0 KiB
Go
package baishun
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"chatapp3-golang/internal/model"
|
|
"chatapp3-golang/internal/service/highwin"
|
|
"chatapp3-golang/internal/utils"
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
const (
|
|
baishunReportTypeStart = "game_start"
|
|
baishunReportTypeSettle = "game_settle"
|
|
baishunReportBetTTL = 24 * time.Hour
|
|
baishunReportBetRedisPrefix = "baishun:report:bet"
|
|
)
|
|
|
|
type baishunGameBetRecord struct {
|
|
SysOrigin string `json:"sysOrigin"`
|
|
RoomID string `json:"roomId"`
|
|
GameID int64 `json:"gameId"`
|
|
GameRoundID string `json:"gameRoundId"`
|
|
UserID int64 `json:"userId"`
|
|
Bet int64 `json:"bet"`
|
|
}
|
|
|
|
func (s *BaishunService) HandleReport(ctx context.Context, req BaishunReportRequest, rawJSON string) baishunStandardResponse {
|
|
resp := baishunStandardResponse{
|
|
Code: 0,
|
|
Message: "succeed",
|
|
UniqueID: s.uniqueID(),
|
|
Data: map[string]any{},
|
|
}
|
|
|
|
sysOrigin := ""
|
|
if session, ok := s.findSessionByToken(ctx, req.SSToken, req.UserID); ok {
|
|
sysOrigin = session.SysOrigin
|
|
if err := s.handleReportHighWins(ctx, session.SysOrigin, req); err != nil {
|
|
log.Printf("handle baishun report high win failed userId=%s reportType=%s: %v", req.UserID, req.ReportType, err)
|
|
}
|
|
}
|
|
|
|
s.saveCallbackLog(
|
|
ctx,
|
|
"report",
|
|
rawJSON,
|
|
utils.MustJSONString(resp, ""),
|
|
sysOrigin,
|
|
req.UserID,
|
|
nil,
|
|
stringPtr(reportGameRoundID(req.ReportMsg)),
|
|
baishunCallbackStatusSuccess,
|
|
0,
|
|
resp.Message,
|
|
)
|
|
return resp
|
|
}
|
|
|
|
func (s *BaishunService) handleReportHighWins(ctx context.Context, sysOrigin string, req BaishunReportRequest) error {
|
|
switch strings.ToLower(strings.TrimSpace(req.ReportType)) {
|
|
case baishunReportTypeStart:
|
|
return s.rememberBaishunGameBets(ctx, sysOrigin, req.ReportMsg)
|
|
case baishunReportTypeSettle:
|
|
return s.publishBaishunGameHighWins(ctx, sysOrigin, req.ReportMsg)
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (s *BaishunService) rememberBaishunGameBets(ctx context.Context, sysOrigin string, payload map[string]any) error {
|
|
if s == nil || s.repo.Redis == nil {
|
|
return nil
|
|
}
|
|
roomID := reportText(payload, "room_id", "roomId")
|
|
gameRoundID := reportGameRoundID(payload)
|
|
if strings.TrimSpace(roomID) == "" || strings.TrimSpace(gameRoundID) == "" {
|
|
return nil
|
|
}
|
|
gameID := reportInt64(payload, "game_id", "gameId")
|
|
for _, player := range reportPlayers(payload) {
|
|
if reportInt64(player, "is_ai", "isAi") != 0 {
|
|
continue
|
|
}
|
|
userID := reportInt64(player, "user_id", "userId")
|
|
bet := reportInt64(player, "bet")
|
|
if userID <= 0 || bet <= 0 {
|
|
continue
|
|
}
|
|
record := baishunGameBetRecord{
|
|
SysOrigin: normalizeAdminSysOrigin(sysOrigin),
|
|
RoomID: roomID,
|
|
GameID: gameID,
|
|
GameRoundID: gameRoundID,
|
|
UserID: userID,
|
|
Bet: bet,
|
|
}
|
|
body, err := json.Marshal(record)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := s.repo.Redis.Set(ctx, baishunGameBetKey(record.SysOrigin, gameRoundID, userID), string(body), baishunReportBetTTL).Err(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *BaishunService) publishBaishunGameHighWins(ctx context.Context, sysOrigin string, payload map[string]any) error {
|
|
if s == nil || s.highWinBroadcaster == nil || s.repo.Redis == nil {
|
|
return nil
|
|
}
|
|
sysOrigin = normalizeAdminSysOrigin(sysOrigin)
|
|
roomID := reportText(payload, "room_id", "roomId")
|
|
gameRoundID := reportGameRoundID(payload)
|
|
if strings.TrimSpace(roomID) == "" || strings.TrimSpace(gameRoundID) == "" {
|
|
return nil
|
|
}
|
|
gameID := reportInt64(payload, "game_id", "gameId")
|
|
gameCover := s.resolveBaishunReportGameCover(ctx, sysOrigin, roomID, gameID)
|
|
|
|
for _, player := range reportPlayers(payload) {
|
|
if reportInt64(player, "is_ai", "isAi") != 0 {
|
|
continue
|
|
}
|
|
userID := reportInt64(player, "user_id", "userId")
|
|
reward := reportInt64(player, "reward")
|
|
if userID <= 0 || reward <= 0 {
|
|
continue
|
|
}
|
|
betRecord, ok, err := s.loadBaishunGameBet(ctx, sysOrigin, gameRoundID, userID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !ok || betRecord.Bet <= 0 {
|
|
continue
|
|
}
|
|
multiple := highwin.Multiple(reward, betRecord.Bet)
|
|
if !highwin.ShouldBroadcast(multiple, reward) {
|
|
continue
|
|
}
|
|
data := map[string]any{
|
|
"gameId": gameID,
|
|
"gameRoundId": gameRoundID,
|
|
"gameUrl": gameCover,
|
|
"betAmount": betRecord.Bet,
|
|
"currencyDiff": reward,
|
|
"rank": reportInt64(player, "rank"),
|
|
"score": reportInt64(player, "score"),
|
|
}
|
|
if err := highwin.SendRegionBroadcast(ctx, s.highWinBroadcaster, highwin.BroadcastEvent{
|
|
SysOrigin: sysOrigin,
|
|
Type: highwin.MessageTypeBaishunWin,
|
|
UserID: userID,
|
|
RoomID: roomID,
|
|
Multiple: multiple,
|
|
Amount: reward,
|
|
Data: data,
|
|
}); err != nil {
|
|
log.Printf("send baishun game high win region broadcast failed roundId=%s userId=%d: %v", gameRoundID, userID, err)
|
|
}
|
|
_ = s.repo.Redis.Del(ctx, baishunGameBetKey(sysOrigin, gameRoundID, userID)).Err()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *BaishunService) loadBaishunGameBet(ctx context.Context, sysOrigin, gameRoundID string, userID int64) (baishunGameBetRecord, bool, error) {
|
|
raw, err := s.repo.Redis.Get(ctx, baishunGameBetKey(sysOrigin, gameRoundID, userID)).Result()
|
|
if errors.Is(err, redis.Nil) {
|
|
return baishunGameBetRecord{}, false, nil
|
|
}
|
|
if err != nil {
|
|
return baishunGameBetRecord{}, false, err
|
|
}
|
|
var record baishunGameBetRecord
|
|
if err := json.Unmarshal([]byte(raw), &record); err != nil {
|
|
return baishunGameBetRecord{}, false, err
|
|
}
|
|
return record, true, nil
|
|
}
|
|
|
|
func (s *BaishunService) resolveBaishunReportGameCover(ctx context.Context, sysOrigin, roomID string, gameID int64) string {
|
|
var state model.BaishunRoomState
|
|
if strings.TrimSpace(roomID) != "" {
|
|
err := s.repo.DB.WithContext(ctx).
|
|
Where("sys_origin = ? AND room_id = ?", normalizeAdminSysOrigin(sysOrigin), roomID).
|
|
First(&state).Error
|
|
if err == nil && strings.TrimSpace(state.CurrentGameCover) != "" {
|
|
return strings.TrimSpace(state.CurrentGameCover)
|
|
}
|
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return ""
|
|
}
|
|
}
|
|
if gameID <= 0 {
|
|
return ""
|
|
}
|
|
profile, err := s.activeProfile(ctx, sysOrigin)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
var catalog model.BaishunGameCatalog
|
|
if err := s.repo.DB.WithContext(ctx).
|
|
Where("sys_origin = ? AND profile = ? AND vendor_game_id = ?", normalizeAdminSysOrigin(sysOrigin), profile, gameID).
|
|
First(&catalog).Error; err != nil {
|
|
return ""
|
|
}
|
|
return strings.TrimSpace(catalog.Cover)
|
|
}
|
|
|
|
func reportGameRoundID(payload map[string]any) string {
|
|
return reportText(payload, "game_round_id", "gameRoundId")
|
|
}
|
|
|
|
func reportPlayers(payload map[string]any) []map[string]any {
|
|
raw, exists := payload["players"]
|
|
if !exists {
|
|
return nil
|
|
}
|
|
switch typed := raw.(type) {
|
|
case []map[string]any:
|
|
return typed
|
|
case []any:
|
|
players := make([]map[string]any, 0, len(typed))
|
|
for _, item := range typed {
|
|
if player, ok := item.(map[string]any); ok {
|
|
players = append(players, player)
|
|
}
|
|
}
|
|
return players
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func reportText(payload map[string]any, keys ...string) string {
|
|
for _, key := range keys {
|
|
if value, exists := payload[key]; exists {
|
|
text := strings.TrimSpace(toString(value))
|
|
if text != "" {
|
|
return text
|
|
}
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func reportInt64(payload map[string]any, keys ...string) int64 {
|
|
for _, key := range keys {
|
|
value, exists := payload[key]
|
|
if !exists {
|
|
continue
|
|
}
|
|
switch typed := value.(type) {
|
|
case int:
|
|
return int64(typed)
|
|
case int64:
|
|
return typed
|
|
case float64:
|
|
return int64(typed)
|
|
case json.Number:
|
|
parsed, _ := typed.Int64()
|
|
return parsed
|
|
case string:
|
|
parsed, _ := strconv.ParseInt(strings.TrimSpace(typed), 10, 64)
|
|
return parsed
|
|
default:
|
|
parsed, _ := strconv.ParseInt(strings.TrimSpace(fmt.Sprint(typed)), 10, 64)
|
|
return parsed
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func baishunGameBetKey(sysOrigin, gameRoundID string, userID int64) string {
|
|
return strings.Join([]string{
|
|
baishunReportBetRedisPrefix,
|
|
normalizeAdminSysOrigin(sysOrigin),
|
|
strings.TrimSpace(gameRoundID),
|
|
strconv.FormatInt(userID, 10),
|
|
}, ":")
|
|
}
|