From 4a0138fdd5785f4eee378f549145e164a01a6e68 Mon Sep 17 00:00:00 2001 From: udieudie Date: Thu, 29 May 2025 01:16:44 +0800 Subject: [PATCH 1/6] =?UTF-8?q?david/feat:=E4=BF=AE=E5=A4=8D=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E5=AF=B9=E5=B1=80=E6=95=B0=E6=8D=AE=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/manager/douyin/dy_service_manager.go | 2 +- app/manager/live_room_mamanger.go | 17 ++++++++++------- app/manager/live_room_mysql_storage.go | 7 ++++++- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/app/manager/douyin/dy_service_manager.go b/app/manager/douyin/dy_service_manager.go index e466fd4..771b386 100644 --- a/app/manager/douyin/dy_service_manager.go +++ b/app/manager/douyin/dy_service_manager.go @@ -306,7 +306,7 @@ func SyncGameStatusToDouYin(accessToken string, anchorOpenId string, liveRoomId requestBody := struct { AnchorOpenId string `json:"anchor_open_id"` Appid string `json:"appid"` - RoomId string `json:"roomid"` + RoomId string `json:"room_id"` RoundId int64 `json:"round_id"` StartTime int64 `json:"start_time"` // 本局开始时间,秒级时间戳 EndTime int64 `json:"end_time"` // 本局结束时间,秒级时间戳。同步的对局状态为对局结束时,该字段必传。 diff --git a/app/manager/live_room_mamanger.go b/app/manager/live_room_mamanger.go index 47b7518..2b176df 100644 --- a/app/manager/live_room_mamanger.go +++ b/app/manager/live_room_mamanger.go @@ -159,13 +159,16 @@ func (lrm *LiveRoomManager) GetLiveInfo(liveRoomID string) (*LiveRoomInfo, error } return &LiveRoomInfo{ - LiveRoomId: liveMysqlInfo.LiveRoomId, - State: liveMysqlInfo.State, - Times: liveMysqlInfo.Times, - StartAt: liveMysqlInfo.StartAt, - EndAt: liveMysqlInfo.EndAt, - CreateAt: liveMysqlInfo.CreateAt, - UpdateAt: liveMysqlInfo.UpdateAt, + LiveRoomId: liveMysqlInfo.LiveRoomId, + AnchorOpenId: liveMysqlInfo.AnchorOpenId, + AvatarUrl: liveMysqlInfo.AvatarUrl, + NickName: liveMysqlInfo.NickName, + State: liveMysqlInfo.State, + Times: liveMysqlInfo.Times, + StartAt: liveMysqlInfo.StartAt, + EndAt: liveMysqlInfo.EndAt, + CreateAt: liveMysqlInfo.CreateAt, + UpdateAt: liveMysqlInfo.UpdateAt, }, nil // 返回 LiveRoomStatus 和 false } diff --git a/app/manager/live_room_mysql_storage.go b/app/manager/live_room_mysql_storage.go index faa2561..0150bc5 100644 --- a/app/manager/live_room_mysql_storage.go +++ b/app/manager/live_room_mysql_storage.go @@ -157,13 +157,18 @@ func (lrm *LiveRoomMysqlStorage) GetLiveRoom(liveRoomID string) (*LiveRoomMysqlI // 执行 SQL 查询 err := db.GetDB().QueryRow(` - SELECT live_room_id, state, times, create_at, update_at + SELECT live_room_id, anchor_open_id, avatar_url, nick_name, state, times, start_at, end_at, create_at, update_at FROM live_room WHERE live_room_id = ? `, liveRoomID).Scan( &liveRoom.LiveRoomId, + &liveRoom.AnchorOpenId, + &liveRoom.AvatarUrl, + &liveRoom.NickName, &liveRoom.State, &liveRoom.Times, + &liveRoom.StartAt, + &liveRoom.EndAt, &liveRoom.CreateAt, &liveRoom.UpdateAt, ) -- Gitee From 5930f2889b878c3c4cbe0011bcdc475bbaaaf757 Mon Sep 17 00:00:00 2001 From: udieudie Date: Mon, 2 Jun 2025 23:36:24 +0800 Subject: [PATCH 2/6] =?UTF-8?q?david/feat:=E5=A2=9E=E5=8A=A0=E6=B8=B8?= =?UTF-8?q?=E6=88=8F=E6=95=B0=E6=8D=AE=E7=9A=84=E8=BE=93=E5=85=A5=E5=92=8C?= =?UTF-8?q?=E8=BE=93=E5=87=BA=E7=9A=84=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controller/httpController.go | 87 ++++++++++++++++++++++++++ app/manager/live_room_mamanger.go | 40 ++++++++++++ app/manager/live_room_mysql_storage.go | 56 +++++++++++++++++ templates/index.html | 74 ++++++++++++++++++++++ 4 files changed, 257 insertions(+) diff --git a/app/controller/httpController.go b/app/controller/httpController.go index e9994a0..1a7a752 100644 --- a/app/controller/httpController.go +++ b/app/controller/httpController.go @@ -24,7 +24,10 @@ type FinishGameRequest struct { Champion int `json:"champion"` FinishTrackInfo []models.FinishTrackInfo `json:"finish_track_info"` Timestamp int64 `json:"timestamp"` // 修改为 int64 +} +type SetGameDataRequest struct { + Data string `json:"data"` } type RecordClientErrorRequest struct { @@ -132,6 +135,16 @@ func (h *HttpController) RegisterRoutes(router *gin.Engine) { fmt.Println("[DEBUG] /getWorldRecords") // 测试路由是否触发 h.getWorldRecords(c) }) + + authGroup.POST("/setGameData", func(c *gin.Context) { + fmt.Println("[DEBUG] /setGameData") // 测试路由是否触发 + h.setGameData(c) + }) + + authGroup.POST("/getGameData", func(c *gin.Context) { + fmt.Println("[DEBUG] /getGameData") // 测试路由是否触发 + h.getGameData(c) + }) } } @@ -476,6 +489,80 @@ func (h *HttpController) getWorldRecords(c *gin.Context) { }) } +// 示例:获取用户信息的HTTP处理 +func (h *HttpController) setGameData(c *gin.Context) { + var req SetGameDataRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request format"}) + return + } + + // 检查 x-roomid 的值 + roomId := c.GetHeader("x-roomid") + if roomId == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "no roomid"}) + return + } + + liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(roomId) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + return + } + + err = manager.Get().LiveRoomManager().SetGameData(roomId, liveRoomInfo.Times, req.Data) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + return + } + + // 返回处理结果(根据业务需求调整返回结构) + c.JSON(http.StatusOK, gin.H{ + "code": 0, + "message": "success", + "data": gin.H{}, + }) +} + +// 示例:获取用户信息的HTTP处理 +func (h *HttpController) getGameData(c *gin.Context) { + // 检查 x-roomid 的值 + roomId := c.GetHeader("x-roomid") + if roomId == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "no roomid"}) + return + } + + liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(roomId) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + return + } + + gameData, err := manager.Get().LiveRoomManager().GetGameData(roomId, liveRoomInfo.Times) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + return + } + + // 返回处理结果(根据业务需求调整返回结构) + c.JSON(http.StatusOK, gin.H{ + "code": 0, + "message": "success", + "data": gin.H{ + "gameData": gameData, + }, + }) +} + // 示例:获取用户信息的HTTP处理 func (h *HttpController) testFailGiftRecord(c *gin.Context) { // 检查 x-roomid 的值 diff --git a/app/manager/live_room_mamanger.go b/app/manager/live_room_mamanger.go index 2b176df..d727475 100644 --- a/app/manager/live_room_mamanger.go +++ b/app/manager/live_room_mamanger.go @@ -42,6 +42,14 @@ type LiveTrackUserInfo struct { UpdateAt sql.NullTime `json:"update_at"` // 使用 NullTime } +type GameDataInfo struct { + LiveRoomId string `json:"live_room_id"` + Times string `json:"times"` + RawData string `json:"raw_data"` + CreateAt sql.NullTime `json:"create_at"` // 使用 NullTime + UpdateAt sql.NullTime `json:"update_at"` // 使用 NullTime +} + // LiveRoomManager 管理直播间的状态 type LiveRoomManager struct { roomUserTrack map[string]map[string]UserTrack @@ -352,3 +360,35 @@ func (lrm *LiveRoomManager) SetLiveRoomFailGiftNum(liveRoomID string, pageNum, p return fmt.Errorf("SetLiveRoomFailGiftNum no mem logic") } + +// SetLiveRoomStatus 设置直播间的状态 +func (lrm *LiveRoomManager) SetGameData(liveRoomID string, times int, rawData string) error { + if config.Get().Database.Enabled { + err := lrm.storage.InsertGameDate(liveRoomID, times, rawData) + if err != nil { + return err + } + return nil + } + + return fmt.Errorf("setGameData no mem logic") +} + +// SetLiveRoomStatus 设置直播间的状态 +func (lrm *LiveRoomManager) GetGameData(liveRoomID string, times int) (*GameDataInfo, error) { + var gameData GameDataInfo + if config.Get().Database.Enabled { + gameDataMysql, err := lrm.storage.GetGameDate(liveRoomID, times) + if err != nil { + return nil, err + } + gameData.LiveRoomId = gameDataMysql.LiveRoomId + gameData.Times = gameDataMysql.Times + gameData.RawData = gameDataMysql.RawData + gameData.CreateAt = gameDataMysql.CreateAt + gameData.UpdateAt = gameDataMysql.UpdateAt + return &gameData, nil + } + + return nil, fmt.Errorf("getGameData no mem logic") +} diff --git a/app/manager/live_room_mysql_storage.go b/app/manager/live_room_mysql_storage.go index 0150bc5..7d56834 100644 --- a/app/manager/live_room_mysql_storage.go +++ b/app/manager/live_room_mysql_storage.go @@ -63,6 +63,14 @@ type LiveRoomResultMysqlInfo struct { UpdateAt sql.NullTime `db:"update_at"` } +type GameDataMysqlInfo struct { + LiveRoomId string `db:"live_room_id"` + Times string `db:"times"` + RawData string `db:"raw_data"` + CreateAt sql.NullTime `db:"create_at"` // 使用 NullTime + UpdateAt sql.NullTime `db:"update_at"` // 使用 NullTime +} + func NewLiveRoomMysqlStorage() (*LiveRoomMysqlStorage, error) { return &LiveRoomMysqlStorage{}, nil @@ -503,3 +511,51 @@ func (lrm *LiveRoomMysqlStorage) SetLiveRoomFailGiftNum(liveRoomID string, pageN } return nil } + +// 插入直播间数据 +func (lrm *LiveRoomMysqlStorage) InsertGameDate(liveRoomID string, times int, rawData string) error { + _, err := db.GetDB().Exec(` + INSERT INTO game_detail_data + (live_room_id, times, raw_data, create_at, update_at) + VALUES + (?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) + `, + liveRoomID, times, rawData) // 更新值参数 + + if err != nil { + return fmt.Errorf("insert Game Date error : %v", err) + } + return nil +} + +// 获取直播间数据 +func (lrm *LiveRoomMysqlStorage) GetGameDate(liveRoomID string, times int) (*GameDataMysqlInfo, error) { + var gameData GameDataMysqlInfo + + err := db.GetDB().QueryRow(` + SELECT live_room_id, times, raw_data, create_at, update_at + FROM game_detail_data + WHERE live_room_id = ? + and times = ? + order by id desc limit 1 + `, liveRoomID, times).Scan( + &gameData.LiveRoomId, + &gameData.Times, + &gameData.RawData, + &gameData.CreateAt, + &gameData.UpdateAt, + ) + + // 处理错误 + if err != nil { + if err == sql.ErrNoRows { + log.Printf("No live room found with ID: %s", liveRoomID) + return nil, err // 没有找到数据,返回 ErrNoRows + } + log.Printf("Error querying live room: %v", err) // 打印其他错误信息 + return nil, err // 返回其他错误 + } + + // 查询成功,返回结果 + return &gameData, nil +} diff --git a/templates/index.html b/templates/index.html index 5625439..278adc6 100644 --- a/templates/index.html +++ b/templates/index.html @@ -116,6 +116,16 @@
+
+
+ +
+
+ + +
+ + @@ -1308,6 +1318,70 @@ } } + function sendGameData(){ + const url = httpRequestMethod + `://${ip}/api/v1/auth/setGameData`; + + liveRoomID = document.getElementById('liveRoomId').value; + if(liveRoomID == ''){ + alert("请填写直播间号") + return + } + + const gameData = document.getElementById('gameData').value + if(gameData==''){ + alert("请填写游戏数据") + return + } + + // 直播间id放在header中 + const headers = { + 'Authorization': 'Bearer ' + liveRoomAuthToken, + 'Content-Type': 'application/json', + 'x-roomid': liveRoomID, + }; + + // 构造游戏数据,放到名为data的key中 + const data = { + "data": gameData + } + + sendPostRequest(url, data, headers).then(res=>{ + consoleText("发送游戏数据,获取res :", res) + }); + } + + function getGameData(){ + const url = httpRequestMethod + `://${ip}/api/v1/auth/getGameData`; + + liveRoomID = document.getElementById('liveRoomId').value; + if(liveRoomID == ''){ + alert("请填写直播间号") + return + } + + const headers = { + 'Authorization': 'Bearer ' + liveRoomAuthToken, + 'Content-Type': 'application/json', + 'x-roomid': liveRoomID, + }; + + const data = {} + + sendPostRequest(url, data, headers).then(res=>{ + consoleText("获取游戏数据,获取res :", res, typeof res) + resObj = JSON.parse(res) + console.log("获取游戏数据,resObj.data :", resObj.data) + console.log("获取游戏数据,resObj.data.gameData :", resObj.data.gameData) + // 获取游戏数据的原始json字符串 + let gameDataStr = resObj.data.gameData.raw_data + console.log("gameDataStr : ", gameDataStr) + // 字符串转成对象,获得最终的游戏数据的对象 + let gameData = JSON.parse(gameDataStr) + console.log("gameData : ", gameData) + }); + } + + function sendGetRequest(url, params = {}, headers = {}) { return new Promise((resolve, reject) => { // 构造查询字符串 -- Gitee From a0f735748a9778753af3d0aa769aee09dd2a08eb Mon Sep 17 00:00:00 2001 From: udieudie Date: Mon, 2 Jun 2025 23:41:54 +0800 Subject: [PATCH 3/6] =?UTF-8?q?david/feat:=E5=A2=9E=E5=8A=A0=E5=AF=B9?= =?UTF-8?q?=E5=B1=80=E7=BB=93=E6=9D=9F=E7=9A=84=E6=97=B6=E5=80=99=EF=BC=8C?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E6=B8=B8=E6=88=8F=E6=95=B0=E6=8D=AE=E7=9A=84?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controller/httpController.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app/controller/httpController.go b/app/controller/httpController.go index 1a7a752..91fe4a6 100644 --- a/app/controller/httpController.go +++ b/app/controller/httpController.go @@ -533,14 +533,26 @@ func (h *HttpController) getGameData(c *gin.Context) { // 检查 x-roomid 的值 roomId := c.GetHeader("x-roomid") if roomId == "" { - c.JSON(http.StatusBadRequest, gin.H{"error": "no roomid"}) + c.JSON(http.StatusBadRequest, gin.H{ + "error": "no roomid", + "errorCode": 10403, + }) return } liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(roomId) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ - "error": err.Error(), + "error": err.Error(), + "errorCode": 10404, + }) + return + } + + if liveRoomInfo.State == "end" { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "game not start", + "errorCode": 10101, }) return } @@ -548,7 +560,8 @@ func (h *HttpController) getGameData(c *gin.Context) { gameData, err := manager.Get().LiveRoomManager().GetGameData(roomId, liveRoomInfo.Times) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ - "error": err.Error(), + "error": err.Error(), + "errorCode": 500, }) return } -- Gitee From 265282c6afdb3fc781e8e144f5afb35199e268b1 Mon Sep 17 00:00:00 2001 From: udieudie Date: Wed, 4 Jun 2025 16:32:00 +0800 Subject: [PATCH 4/6] =?UTF-8?q?david/feat:=E5=A2=9E=E5=8A=A0=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E7=9A=84=E6=97=B6=E5=80=99=E4=BB=8E=E6=9F=90=E4=B8=AA?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E7=82=B9=E5=9B=9E=E6=94=BE=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=9A=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controller/indexController.go | 18 ++- app/manager/gift_record_manager.go | 52 ++++++++- app/manager/gift_record_mysql_storage.go | 64 +++++++++++ app/manager/live_room_mamanger.go | 49 +++++++- app/manager/live_room_mysql_storage.go | 66 +++++++++++ app/service/live_room_service.go | 140 ++++++++++++++++++++++- app/utils/utils.go | 9 ++ templates/index.html | 36 +++++- 8 files changed, 415 insertions(+), 19 deletions(-) diff --git a/app/controller/indexController.go b/app/controller/indexController.go index 60170a8..d8db921 100644 --- a/app/controller/indexController.go +++ b/app/controller/indexController.go @@ -98,17 +98,8 @@ func (i *IndexController) Regist(ctx *gin.Context) { fmt.Println("websocket error:", err) return } - // 从请求中获取直播间ID - //liveRoomID := ctx.Query("liveRoomID") - //userId := ctx.Query("userId") - //userName := ctx.Query("userName") - liveRoomToken := ctx.Query("liveRoomToken") - //if liveRoomID == "" { - // fmt.Println("直播间ID为空") - // conn.Close() - // return - //} + liveRoomToken := ctx.Query("liveRoomToken") if liveRoomToken == "" { fmt.Println("直播间token为空") @@ -161,6 +152,13 @@ func (i *IndexController) Regist(ctx *gin.Context) { i.returnGenTokenMsg(conn, loginToken, liveRoomUserInfo.RoomId) + backDataByTime := ctx.Query("backDataByTime") + if !(backDataByTime == "") { + backDataByTimeI64, _ := strconv.ParseInt(backDataByTime, 10, 32) + + go service.DealBackDataByTime(conn, liveRoomInfo.LiveRoomId, liveRoomInfo.Times, backDataByTimeI64) + } + // 得到客户的连接ip和端口 fmt.Println("client connect:", conn.RemoteAddr()) go i.Do(conn, liveRoomUserInfo.RoomId) diff --git a/app/manager/gift_record_manager.go b/app/manager/gift_record_manager.go index 33336f6..a004d14 100644 --- a/app/manager/gift_record_manager.go +++ b/app/manager/gift_record_manager.go @@ -222,7 +222,7 @@ func (grm *GiftRecordManager) GetTotalScoreByRoomId(liveRoomID string, times int return totalScore, nil } -// GetGiftRecordByLiveRoomAndTimes 获取指定用户在某个直播间内赠送的礼物数量 +// GetGiftRecordByLiveRoomAndTimes 获取某个直播间内赠送的礼物数据 func (grm *GiftRecordManager) GetGiftRecordByLiveRoomAndTimes(liveRoomID string, times int) ([]GiftRecord, error) { var giftRecords []GiftRecord @@ -263,7 +263,7 @@ func (grm *GiftRecordManager) GetGiftRecordByLiveRoomAndTimes(liveRoomID string, return giftRecords, fmt.Errorf("database is not enabled") } -// GetGiftRecordByLiveRoomAndTimes 获取指定用户在某个直播间内赠送的礼物数量 +// GetGiftRecordWithUserInfoByLiveRoomAndTimes 获取在某个直播间内赠送的礼物加用户的数据 func (grm *GiftRecordManager) GetGiftRecordWithUserInfoByLiveRoomAndTimes(liveRoomID string, times int) ([]GiftRecordWithUserInfo, error) { var giftRecordsWithUserInfo []GiftRecordWithUserInfo @@ -309,7 +309,53 @@ func (grm *GiftRecordManager) GetGiftRecordWithUserInfoByLiveRoomAndTimes(liveRo return giftRecordsWithUserInfo, fmt.Errorf("database is not enabled") } -// GetTotalScoreByRoomId 获取某场比赛的总积分 +// GetGiftRecordWithUserInfoByLiveRoomAndTimesByTime 获取在某个直播间某个时间点后赠送的礼物加用户的数据 +func (grm *GiftRecordManager) GetGiftRecordWithUserInfoByLiveRoomAndTimesByTime(liveRoomID string, times int, timeStr string) ([]GiftRecordWithUserInfo, error) { + var giftRecordsWithUserInfo []GiftRecordWithUserInfo + + if config.Get().Database.Enabled { + // 调用 MySQL 存储层的方法 + giftRecordInfos, err := grm.storage.GetGiftRecordWithUserInfoByLiveRoomAndTimesByTime(liveRoomID, times, timeStr) + if err != nil { + return nil, err + } + + // 将 GiftRecordMysqlInfo 转换为 GiftRecord + for _, recordInfo := range giftRecordInfos { + giftRecordWithUserInfo := GiftRecordWithUserInfo{ + MsgId: recordInfo.MsgId, + LiveRoomId: recordInfo.LiveRoomId, + Times: recordInfo.Times, + Track: recordInfo.Track, + UserId: recordInfo.UserId, + GiftId: recordInfo.GiftId, + GiftName: recordInfo.GiftName, + Amount: recordInfo.Amount, + Value: recordInfo.OneValue, // Value 对应 单个礼物的value + TotalValue: recordInfo.TotalValue, + Score: recordInfo.Score, + TotalScore: recordInfo.TotalScore, + GiftLevel: recordInfo.GiftLevel, + GiftUpgrading: recordInfo.GiftUpgrading, + UserName: recordInfo.UserName, + UserHeadImg: recordInfo.UserHeadImg, + UserLevel: recordInfo.UserLevel, + UserScore: recordInfo.UserScore, + ExpireAt: recordInfo.ExpireAt, + CreateAt: recordInfo.CreateAt, + UpdateAt: recordInfo.UpdateAt, + } + giftRecordsWithUserInfo = append(giftRecordsWithUserInfo, giftRecordWithUserInfo) + } + + return giftRecordsWithUserInfo, nil + } + + // 如果 MySQL 未启用,返回错误 + return giftRecordsWithUserInfo, fmt.Errorf("database is not enabled") +} + +// GetAccScoreByRoomIdAndUserId 获取某场比赛的总积分 func (grm *GiftRecordManager) GetAccScoreByRoomIdAndUserId(liveRoomID string, times int, userId string) (int, error) { if config.Get().Database.Enabled { var accScore int diff --git a/app/manager/gift_record_mysql_storage.go b/app/manager/gift_record_mysql_storage.go index eb21867..9773509 100644 --- a/app/manager/gift_record_mysql_storage.go +++ b/app/manager/gift_record_mysql_storage.go @@ -395,6 +395,70 @@ func (grm *GiftRecordMysqlStorage) GetGiftRecordWithUserInfoByLiveRoomAndTimes(l return giftRecordList, nil } +// GetGiftRecordWithUserInfoByLiveRoomAndTimesByTime 查询本场对局某个时间点后的记录 +func (grm *GiftRecordMysqlStorage) GetGiftRecordWithUserInfoByLiveRoomAndTimesByTime(liveRoomId string, times int, timeStr string) ([]GiftRecordWithUserInfoMysqlInfo, error) { + // 构建查询语句 + query := fmt.Sprintf(` + SELECT grs.msg_id, grs.live_room_id, grs.times, grs.track, grs.user_id, grs.gift_id, + grs.gift_name, grs.amount, grs.one_value, grs.total_value, + grs.score, grs.total_score, grs.gift_level, grs.gift_upgrading, + us.user_name, us.head_img, us.level, us.score, us.expire_at, + grs.create_at, grs.update_at + FROM gift_records grs + left join users us on us.user_id = grs.user_id + WHERE grs.live_room_id = ? AND grs.times = ? And grs.create_at >= ? + `) + + // 准备查询参数 + args := make([]interface{}, 0, 3) + args = append(args, liveRoomId) + args = append(args, times) + args = append(args, timeStr) + + // 查询数据 + rows, err := db.GetDB().Query(query, args...) + if err != nil { + log.Printf("Error querying gift records: %v", err) + return nil, err + } + defer rows.Close() + + // 遍历查询结果 + var giftRecordList []GiftRecordWithUserInfoMysqlInfo + for rows.Next() { + var record GiftRecordWithUserInfoMysqlInfo + if err := rows.Scan( + &record.MsgId, + &record.LiveRoomId, + &record.Times, + &record.Track, + &record.UserId, + &record.GiftId, + &record.GiftName, + &record.Amount, + &record.OneValue, + &record.TotalValue, + &record.Score, + &record.TotalScore, + &record.GiftLevel, + &record.GiftUpgrading, + &record.UserName, + &record.UserHeadImg, + &record.UserLevel, + &record.UserScore, + &record.ExpireAt, + &record.CreateAt, + &record.UpdateAt, + ); err != nil { + log.Printf("Error scanning gift record: %v", err) + return nil, err + } + giftRecordList = append(giftRecordList, record) + } + + return giftRecordList, nil +} + func (grm *GiftRecordMysqlStorage) SetGiftRecordLevel(msgId string, giftLevel, giftUpgrading int) error { _, err := db.GetDB().Exec(` update gift_records diff --git a/app/manager/live_room_mamanger.go b/app/manager/live_room_mamanger.go index d727475..0bae9e1 100644 --- a/app/manager/live_room_mamanger.go +++ b/app/manager/live_room_mamanger.go @@ -42,6 +42,20 @@ type LiveTrackUserInfo struct { UpdateAt sql.NullTime `json:"update_at"` // 使用 NullTime } +type LiveTrackWithUserInfo struct { + LiveRoomId string `json:"live_room_id"` + UserId string `json:"user_id"` + Times int `json:"times"` + Track int `json:"track"` + UserName string `json:"user_name"` + UserHeadImg string `json:"head_img"` + UserLevel int `json:"level"` + UserScore int `json:"score"` + UserExpireAt sql.NullTime `json:"expire_at"` + CreateAt sql.NullTime `json:"create_at"` // 使用 NullTime + UpdateAt sql.NullTime `json:"update_at"` // 使用 NullTime +} + type GameDataInfo struct { LiveRoomId string `json:"live_room_id"` Times string `json:"times"` @@ -115,7 +129,7 @@ func (lrm *LiveRoomManager) CreateLiveRoomIfNotExist(liveRoomID, AnchorOpenId, A return "", fmt.Errorf("CreateLiveRoomIfNotExist has no mem logic : ") } -// SetLiveRoomStatus 设置直播间的状态 +// JoinLiveRoomCamp 用户加入直播间的某个阵营 func (lrm *LiveRoomManager) JoinLiveRoomCamp(liveRoomId string, times int, state string, userId string, track int) error { if config.Get().Database.Enabled { _, err := lrm.storage.JoinLiveRoomTrackMysql(liveRoomId, times, state, userId, track) @@ -137,7 +151,7 @@ func (lrm *LiveRoomManager) JoinLiveRoomCamp(liveRoomId string, times int, state return nil } -// GetLiveRoomStatus 获取直播间的状态, 返回的bool是true代表有错误 +// GetLiveTrackInfoByUserId 获取直播间中某个用户的加入阵营数据 func (lrm *LiveRoomManager) GetLiveTrackInfoByUserId(liveRoomID string, userId string) (*LiveTrackUserInfo, error) { if config.Get().Database.Enabled { liveTrackUserMysqlInfo, err := lrm.storage.GetLiveRoomTrackMysql(liveRoomID, userId) @@ -158,6 +172,37 @@ func (lrm *LiveRoomManager) GetLiveTrackInfoByUserId(liveRoomID string, userId s return nil, nil } +// GetLiveTrackInfoByUserId 获取直播间中某个用户的加入阵营数据 +func (lrm *LiveRoomManager) GetLiveTrackInfosWithUserInfoByTime(liveRoomID string, times int, timeStr string) ([]LiveTrackWithUserInfo, error) { + var liveTrackUserInfoList []LiveTrackWithUserInfo + if config.Get().Database.Enabled { + liveTrackUserMysqlInfoList, err := lrm.storage.GetLiveTrackInfosWithUserInfoByTime(liveRoomID, times, timeStr) + if err != nil { + return nil, err + } + + for _, recordInfo := range liveTrackUserMysqlInfoList { + liveTrackUserInfo := LiveTrackWithUserInfo{ + LiveRoomId: recordInfo.LiveRoomId, + UserId: recordInfo.UserId, + Times: recordInfo.Times, + Track: recordInfo.Track, + CreateAt: recordInfo.CreateAt, + UpdateAt: recordInfo.UpdateAt, + UserName: recordInfo.UserName, + UserHeadImg: recordInfo.UserHeadImg, + UserLevel: recordInfo.UserLevel, + UserScore: recordInfo.UserScore, + UserExpireAt: recordInfo.UserExpireAt, + } + liveTrackUserInfoList = append(liveTrackUserInfoList, liveTrackUserInfo) + } + return liveTrackUserInfoList, nil + } + + return nil, nil +} + // GetLiveRoomStatus 获取直播间的状态, 返回的bool是true代表有错误 func (lrm *LiveRoomManager) GetLiveInfo(liveRoomID string) (*LiveRoomInfo, error) { if config.Get().Database.Enabled { diff --git a/app/manager/live_room_mysql_storage.go b/app/manager/live_room_mysql_storage.go index 7d56834..24da640 100644 --- a/app/manager/live_room_mysql_storage.go +++ b/app/manager/live_room_mysql_storage.go @@ -33,6 +33,20 @@ type LiveTrackUserMysqlInfo struct { UpdateAt sql.NullTime `db:"update_at"` // 使用 NullTime } +type LiveTrackWithUserMysqlInfo struct { + LiveRoomId string `db:"live_room_id"` + UserId string `db:"user_id"` + Times int `db:"times"` + Track int `db:"track"` + UserName string `db:"user_name"` + UserHeadImg string `db:"head_img"` + UserLevel int `db:"level"` + UserScore int `db:"score"` + UserExpireAt sql.NullTime `db:"expire_at"` + CreateAt sql.NullTime `db:"create_at"` // 使用 NullTime + UpdateAt sql.NullTime `db:"update_at"` // 使用 NullTime +} + // LiveRoomResult 表示 live_room_result 表的结构 type LiveRoomResultMysqlInfo struct { LiveRoomID string `db:"live_room_id"` @@ -325,6 +339,58 @@ func (lrm *LiveRoomMysqlStorage) GetLiveRoomTrackMysql(liveRoomId string, userId } +// 查询用户参与阵营的数据,关联用户数据 +func (lrm *LiveRoomMysqlStorage) GetLiveTrackInfosWithUserInfoByTime(liveRoomId string, times int, timeStr string) ([]LiveTrackWithUserMysqlInfo, error) { + query := fmt.Sprintf(` + SELECT lt.live_room_id, lt.user_id, lt.times, lt.track, lt.create_at, lt.update_at, + us.user_name, us.head_img, us.level, us.score, us.expire_at + FROM live_track lt + left join users us on us.user_id = lt.user_id + WHERE lt.live_room_id = ? and + lt.times = ? and + lt.create_at >= ? + `) + + // 准备查询参数 + args := make([]interface{}, 0, 3) + args = append(args, liveRoomId) + args = append(args, times) + args = append(args, timeStr) + + // 查询数据 + rows, err := db.GetDB().Query(query, args...) + if err != nil { + log.Printf("Error querying gift records: %v", err) + return nil, err + } + defer rows.Close() + + // 遍历查询结果 + var liveTrackUserMysqlInfoList []LiveTrackWithUserMysqlInfo + for rows.Next() { + var record LiveTrackWithUserMysqlInfo + if err := rows.Scan( + &record.LiveRoomId, + &record.UserId, + &record.Times, + &record.Track, + &record.CreateAt, + &record.UpdateAt, + &record.UserName, + &record.UserHeadImg, + &record.UserLevel, + &record.UserScore, + &record.UserExpireAt, + ); err != nil { + log.Printf("Error scanning gift record: %v", err) + return nil, err + } + liveTrackUserMysqlInfoList = append(liveTrackUserMysqlInfoList, record) + } + + return liveTrackUserMysqlInfoList, nil +} + // BatchInsertLiveRoomResults 批量插入直播间的比赛结果到数据库 func (lrm *LiveRoomMysqlStorage) BatchInsertLiveRoomResults(results []LiveRoomResultMysqlInfo) error { stmt, err := db.GetDB().Prepare(`INSERT INTO live_room_result ( diff --git a/app/service/live_room_service.go b/app/service/live_room_service.go index 782234c..c7a2d6a 100644 --- a/app/service/live_room_service.go +++ b/app/service/live_room_service.go @@ -7,6 +7,7 @@ import ( "database/sql" "fmt" "github.com/google/uuid" + "github.com/gorilla/websocket" "strconv" "time" ) @@ -89,7 +90,6 @@ func (ls LiveRoomService) OneUserJoinTrack(liveRoomID string, userId string, tra }, } - //i.eventManager.AddEventData(liveRoomID, data) manager.Get().EventManager().AddEventData(liveRoomID, data) return nil } @@ -265,7 +265,7 @@ func (ls LiveRoomService) OneUserSendGift(msgID string, liveRoomID string, userI Camp: track, SecGiftID: giftId, GiftNum: giftNum, - GiftValue: giftValue, + GiftValue: giftValue * giftNum, Name: giftName, Nickname: userName, Level: level, @@ -666,3 +666,139 @@ func DealUserLiveRoomResultScoreToUser() error { } return nil } + +// 处理升级,并送礼物 +func DealBackDataByTime(conn *websocket.Conn, liveRoomId string, times int, timestamp int64) error { + // 处理时间戳,转换成时间字符串 + sec := timestamp / 1000 + nsec := (timestamp % 1000) * 1000000 + // 创建时间对象 + t := time.Unix(sec, nsec) + // 格式化为字符串 + timeStr := t.Format("2006-01-02 15:04:05") + fmt.Println(timeStr) // 输出:2021-10-01 12:00:00 + + //处理对局数据 + liveTrackUserInfoList, _ := manager.Get().LiveRoomManager().GetLiveTrackInfosWithUserInfoByTime(liveRoomId, times, timeStr) + for _, info := range liveTrackUserInfoList { + createTimestamp, hasErr := utils.ToMillisTimStamp(info.CreateAt) + if hasErr { + createTimestamp = time.Now().UnixMilli() + } + + // 创建一个礼物事件 + data := models.LiveEventData{ + Event: "broad_join_track", + Data: struct { + MsgID string `json:"msg_id"` // 事件的ID + SecOpenID string `json:"sec_openid"` // 用户的加密openid + Type string `json:"type"` // 事件类型:comment, gift, like + Content string `json:"content"` // 评论内容(仅评论有效) + Camp int `json:"camp"` // 评论内容(仅评论有效) + SecGiftID string `json:"sec_gift_id"` // 加密的礼物id(仅礼物有效) + GiftNum int `json:"gift_num"` // 送出的礼物数量(仅礼物有效) + GiftValue int `json:"gift_value"` // 礼物总价值,单位分(仅礼物有效) + Name string `json:"name"` // 用户昵称 + Level int `json:"level"` // 用户等级 + AccGiftScore int `json:"acc_gift_score"` // 直播间当前用户累计礼物价值 + LikeNum string `json:"like_num"` // 点赞数量(仅点赞有效) + AvatarURL string `json:"avatar_url"` // 用户头像 + Nickname string `json:"nickname"` // 用户昵称 + UserScore int `json:"user_score"` // 用户积分 + GiftLevel int `json:"gift_level"` // 礼物等级 + GiftUpgrading int `json:"gift_upgrading"` // 礼物当前次升级 + GameScore int `json:"game_score"` // 游戏当局分数 + Timestamp int64 `json:"timestamp"` // 事件时间戳 + }{ + MsgID: uuid.New().String(), + SecOpenID: info.UserId, + Type: "broad_join_track", + Content: strconv.Itoa(info.Track), + Camp: info.Track, + SecGiftID: "n1/Dg1905sj1FyoBlQBvmbaDZFBNaKuKZH6zxHkv8Lg5x2cRfrKUTb8gzMs=", + GiftNum: 2, + GiftValue: 10, + Name: "", + Nickname: info.UserName, + Level: info.UserLevel, + AvatarURL: info.UserHeadImg, + UserScore: info.UserScore, + Timestamp: createTimestamp, + }, + } + + // 将ack消息发送给前端 + if err := conn.WriteJSON(data); err != nil { + fmt.Println("error sending ack message:", err) + } + } + + //处理礼物数据 + gameScore, _ := manager.Get().GiftRecordManager().GetTotalScoreByRoomId(liveRoomId, times) + + giftWithUserInfos, _ := manager.Get().GiftRecordManager().GetGiftRecordWithUserInfoByLiveRoomAndTimesByTime(liveRoomId, times, timeStr) + for i := 0; i < len(giftWithUserInfos); i++ { + info := giftWithUserInfos[i] + + createTimestamp, hasErr := utils.ToMillisTimStamp(info.CreateAt) + if hasErr { + createTimestamp = time.Now().UnixMilli() + } + + accScore, err := manager.Get().GiftRecordManager().GetAccScoreByRoomIdAndUserId(liveRoomId, times, info.UserId) + if err != nil { + accScore = info.TotalScore + } + + // 创建一个礼物事件 + data := models.LiveEventData{ + Event: "broad_live_gift", + Data: struct { + MsgID string `json:"msg_id"` // 事件的ID + SecOpenID string `json:"sec_openid"` // 用户的加密openid + Type string `json:"type"` // 事件类型:comment, gift, like + Content string `json:"content"` // 评论内容(仅评论有效) + Camp int `json:"camp"` // 所属阵营 + SecGiftID string `json:"sec_gift_id"` // 加密的礼物id(仅礼物有效) + GiftNum int `json:"gift_num"` // 送出的礼物数量(仅礼物有效) + GiftValue int `json:"gift_value"` // 礼物总价值,单位分(仅礼物有效) + Name string `json:"name"` // 用户昵称 + Level int `json:"level"` // 用户等级 + AccGiftScore int `json:"acc_gift_score"` // 直播间当前用户累计礼物价值 + LikeNum string `json:"like_num"` // 点赞数量(仅点赞有效) + AvatarURL string `json:"avatar_url"` // 用户头像 + Nickname string `json:"nickname"` // 用户昵称 + UserScore int `json:"user_score"` // 用户积分 + GiftLevel int `json:"gift_level"` // 礼物等级 + GiftUpgrading int `json:"gift_upgrading"` // 礼物当前次升级 + GameScore int `json:"game_score"` // 游戏当局分数 + Timestamp int64 `json:"timestamp"` // 事件时间戳 + }{ + MsgID: uuid.New().String(), + SecOpenID: info.UserId, + Type: "live_gift", + Camp: info.Track, + SecGiftID: info.GiftId, + GiftNum: info.Amount, + GiftValue: info.TotalValue, + Name: info.GiftName, + Nickname: info.UserName, + Level: info.UserLevel, + AccGiftScore: accScore, + AvatarURL: info.UserHeadImg, + UserScore: info.UserScore, + GiftLevel: info.GiftLevel, + GiftUpgrading: info.GiftUpgrading, + GameScore: gameScore, + Timestamp: createTimestamp, + }, + } + + // 将ack消息发送给前端 + if err := conn.WriteJSON(data); err != nil { + fmt.Println("error sending ack message:", err) + } + } + + return nil +} diff --git a/app/utils/utils.go b/app/utils/utils.go index 6e4d4b5..afec125 100644 --- a/app/utils/utils.go +++ b/app/utils/utils.go @@ -7,6 +7,7 @@ import ( "context" "crypto/hmac" "crypto/sha256" + "database/sql" "encoding/hex" "encoding/json" "fmt" @@ -240,3 +241,11 @@ func StrExists(strIds []string, target string) bool { _, exists := msgIDSet[target] return exists } + +// 带毫秒的转换函数 +func ToMillisTimStamp(nt sql.NullTime) (int64, bool) { + if !nt.Valid { + return 0, false + } + return nt.Time.UnixNano() / 1e6, true +} diff --git a/templates/index.html b/templates/index.html index 278adc6..e61954e 100644 --- a/templates/index.html +++ b/templates/index.html @@ -126,8 +126,9 @@
- - +

+ +