diff --git a/app/controller/dyPushController.go b/app/controller/dyPushController.go index 91fc4b5326f9db838107e00d05c1551ad6ea8c8e..961b9b92f4f417f4540b72db6103c1941c5dd40e 100644 --- a/app/controller/dyPushController.go +++ b/app/controller/dyPushController.go @@ -43,6 +43,11 @@ func (h *dyPushController) RegisterRoutes(router *gin.Engine) { h.dyPushZan(c) }) + authGroup.POST("/dyPushFans", func(c *gin.Context) { + fmt.Println("[DEBUG] /dyPushFans") // 测试路由是否触发 + h.dyPushFans(c) + }) + authGroup.HEAD("/dyPushPingLun", func(c *gin.Context) { fmt.Println("[DEBUG] get /dyPushPingLun") // 测试路由是否触发 c.JSON(http.StatusOK, gin.H{ @@ -70,9 +75,13 @@ func (h *dyPushController) RegisterRoutes(router *gin.Engine) { }) }) - authGroup.POST("/dyPushFensi", func(c *gin.Context) { - fmt.Println("[DEBUG] /dyPushFensi") // 测试路由是否触发 - h.dyPushFensi(c) + authGroup.HEAD("/dyPushFans", func(c *gin.Context) { + fmt.Println("[DEBUG] get /dyPushFans") // 测试路由是否触发 + c.JSON(http.StatusOK, gin.H{ + "code": 0, + "message": "success", + "data": gin.H{}, + }) }) authGroup.POST("/dyGetZhenYing", func(c *gin.Context) { @@ -85,6 +94,24 @@ func (h *dyPushController) RegisterRoutes(router *gin.Engine) { h.dyPushZhenYing(c) }) + authGroup.HEAD("/dyGetZhenYing", func(c *gin.Context) { + fmt.Println("[DEBUG] get /dyGetZhenYing") // 测试路由是否触发 + c.JSON(http.StatusOK, gin.H{ + "code": 0, + "message": "success", + "data": gin.H{}, + }) + }) + + authGroup.HEAD("/dyPushZhenYing", func(c *gin.Context) { + fmt.Println("[DEBUG] get /dyPushZhenYing") // 测试路由是否触发 + c.JSON(http.StatusOK, gin.H{ + "code": 0, + "message": "success", + "data": gin.H{}, + }) + }) + } } @@ -326,12 +353,52 @@ func (h *dyPushController) dyPushZan(c *gin.Context) { } // 示例:获取用户信息的HTTP处理 -func (h *dyPushController) dyPushFensi(c *gin.Context) { - //var req FinishGameRequest - //if err := c.ShouldBindJSON(&req); err != nil { - // c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request format"}) - // return - //} +func (h *dyPushController) dyPushFans(c *gin.Context) { + var req []models.FansOneRequest + 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 + } + + // 检查 X-Msg-Type 的值 + msgType := c.GetHeader("X-Msg-Type") + if msgType == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "no Msg type"}) + return + } + + // 检查 X-Nonce-Str 的值 + nonceStr := c.GetHeader("X-Nonce-Str") + if nonceStr == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "no nonce str"}) + return + } + + for _, item := range req { + giftId := "2" + if item.FansClubReasonType == 2 { + // 代表加入粉丝团 + giftId = "2" + } else if item.FansClubReasonType == 1 { + // 代表粉丝团升级 + giftId = "3" + } + + // 代表加入粉丝团 + + err := service.LiveRoomService{}.OneUserSendGift(item.MsgID, roomId, item.SecOpenID, + giftId, 1) + if err != nil { + } + + } // 返回处理结果(根据业务需求调整返回结构) c.JSON(http.StatusOK, gin.H{ @@ -343,27 +410,108 @@ func (h *dyPushController) dyPushFensi(c *gin.Context) { // 示例:获取用户信息的HTTP处理 func (h *dyPushController) dyGetZhenYing(c *gin.Context) { - //var req FinishGameRequest - //if err := c.ShouldBindJSON(&req); err != nil { - // c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request format"}) - // return - //} + var req models.DouYinGetUserGroupRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"dyGetZhenYing error": "invalid request format"}) + return + } + + // 检查 x-roomid 的值 + xRoomId := c.GetHeader("x-roomid") + if xRoomId == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "no roomid"}) + return + } + + if xRoomId != req.RoomId { + c.JSON(http.StatusBadRequest, gin.H{"error": "params check error"}) + return + } + + GameTimes := 1 + status := 1 + liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(req.RoomId) + if err != nil { + GameTimes = 0 + // 返回处理结果(根据业务需求调整返回结构) + c.JSON(http.StatusOK, gin.H{ + "errcode": 0, + "errmsg": "success", + "data": gin.H{ + "round_id": GameTimes, + "round_status": 2, + "user_group_status": 0, + "group_id": "", + }, + }) + return + } + + GameTimes = liveRoomInfo.Times + if liveRoomInfo.State == "start" { + status = 1 + } else { + status = 2 + } + + userTrackInfo, err := manager.Get().LiveRoomManager().GetLiveTrackInfoByUserId(req.RoomId, req.OpenId) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "errcode": 0, + "errmsg": "success", + "data": gin.H{ + "round_id": GameTimes, + "round_status": status, + "user_group_status": 0, + "group_id": "", + }, + }) + return + } // 返回处理结果(根据业务需求调整返回结构) c.JSON(http.StatusOK, gin.H{ - "code": 0, - "message": "success", - "data": gin.H{}, + "errcode": 0, + "errmsg": "success", + "data": gin.H{ + "round_id": GameTimes, + "round_status": status, + "user_group_status": 1, + "group_id": string(userTrackInfo.Track), + }, }) } // 示例:获取用户信息的HTTP处理 func (h *dyPushController) dyPushZhenYing(c *gin.Context) { - //var req FinishGameRequest - //if err := c.ShouldBindJSON(&req); err != nil { - // c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request format"}) - // return - //} + var req models.DouYinPushUserGroupRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"dyGetZhenYing error": "invalid request format"}) + return + } + + // 检查 x-roomid 的值 + xRoomId := c.GetHeader("x-roomid") + if xRoomId == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "no roomid"}) + return + } + + if xRoomId != req.RoomId { + c.JSON(http.StatusBadRequest, gin.H{"error": "params check error"}) + return + } + + trackNum, err := strconv.Atoi(req.GroupId) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "params GroupId check error"}) + return + } + err = service.LiveRoomService{}.OneUserJoinTrack(req.RoomId, req.OpenId, trackNum) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "dou yin push zhen ying but join error" + err.Error()}) + return + } // 返回处理结果(根据业务需求调整返回结构) c.JSON(http.StatusOK, gin.H{ diff --git a/app/controller/httpController.go b/app/controller/httpController.go index 6e803f7246c8ac9dbbfe82b990edc5525cb8d174..e9994a029aaf300349d0f8623a520ece411abac6 100644 --- a/app/controller/httpController.go +++ b/app/controller/httpController.go @@ -44,7 +44,8 @@ type RecordClientErrorRequest struct { } type HttpController struct { - mu sync.Mutex // 添加互斥锁字段 + mu sync.Mutex // 添加互斥锁字段 + testSwitch int } func NewHttpController() *HttpController { @@ -75,6 +76,20 @@ func (h *HttpController) RegisterRoutes(router *gin.Engine) { fmt.Println("[DEBUG] /api/v1/getGiftRequest hit") // 测试路由是否触发 h.GetGiftRequest(c) }) + apiGroup.POST("/OpenSendManyZanRequest", func(c *gin.Context) { + fmt.Println("[DEBUG] /api/v1/OpenSendManyZanRequest hit") // 测试路由是否触发 + h.OpenSendManyZanRequest(c) + }) + + apiGroup.POST("/OpenSendManyRequest", func(c *gin.Context) { + fmt.Println("[DEBUG] /api/v1/OpenSendManyRequest hit") // 测试路由是否触发 + h.OpenSendManyRequest(c) + }) + + apiGroup.POST("/CloseSendManyRequest", func(c *gin.Context) { + fmt.Println("[DEBUG] /api/v1/CloseSendManyRequest hit") // 测试路由是否触发 + h.CloseSendManyRequest(c) + }) //apiGroup.GET("/getToken", h.GetToken) apiGroup.POST("/auth/anchor/login", func(c *gin.Context) { @@ -164,6 +179,199 @@ func (h *HttpController) AuthAnchorLogin(c *gin.Context) { }) } +// 发送批量请求开启 +func (h *HttpController) OpenSendManyZanRequest(c *gin.Context) { + var req models.GiftRequestPayloadArr + 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 + } + + go h.SendManyZanRequest(roomId) + + // 返回处理结果(根据业务需求调整返回结构) + c.JSON(http.StatusOK, gin.H{ + "code": 0, + "message": "success", + "data": gin.H{}, + }) +} + +// 发送批量请求 +func (h *HttpController) SendManyZanRequest(liveRoomID string) { + + if h.testSwitch == 1 { + return + } + + h.testSwitch = 1 + + // 定义 User 结构体 + type User struct { + Username string + UserId string + UserImgHead string + } + + // 初始化 User 数组(包含 3 个元素) + users := [3]User{ + {Username: "Alice", UserId: "1001", UserImgHead: "http://82.157.179.66:8001/static/03763e7c5fd77d3ba9d0ed2b35f5bfeb.jpeg"}, + {Username: "Bob", UserId: "1002", UserImgHead: "http://82.157.179.66:8001/static/16e1041e5e02db1c77678084102a9b6b.jpeg"}, + {Username: "Charlie", UserId: "1003", UserImgHead: "http://82.157.179.66:8001/static/8944face68cc71bc452ea8a4fd0abc5b.jpeg"}, + } + + for i := 0; i < len(users); i++ { + service.LiveRoomService{}.SendTestPingLunNoStoage(liveRoomID, users[i].UserId, users[i].Username, users[i].UserImgHead, i+1) + } + + // 初始化礼物 ID 字符串数组(包含 5 个元素) + giftIds := [1]string{ + "1", + } + + accScore := 0 + for { + if h.testSwitch == 0 { + break + } + + for i := 0; i < len(users); i++ { + for j := 0; j < len(giftIds); j++ { + accScore++ + service.LiveRoomService{}.SendTestGiftNoStoage(liveRoomID, users[i].UserId, users[i].Username, users[i].UserImgHead, + giftIds[j], 1, i+1, accScore) + + time.Sleep(10 * time.Millisecond) + } + } + } + + return +} + +// 发送批量请求开启 +func (h *HttpController) OpenSendManyRequest(c *gin.Context) { + var req models.GiftRequestPayloadArr + 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 + } + + go h.SendManyRequest(roomId) + + // 返回处理结果(根据业务需求调整返回结构) + c.JSON(http.StatusOK, gin.H{ + "code": 0, + "message": "success", + "data": gin.H{}, + }) +} + +// 发送批量请求 +func (h *HttpController) SendManyRequest(liveRoomID string) { + + if h.testSwitch == 1 { + return + } + + h.testSwitch = 1 + + // 定义 User 结构体 + type User struct { + Username string + UserId string + UserImgHead string + } + + // 初始化 User 数组(包含 3 个元素) + users := [3]User{ + {Username: "Alice", UserId: "1001", UserImgHead: "http://82.157.179.66:8001/static/03763e7c5fd77d3ba9d0ed2b35f5bfeb.jpeg"}, + {Username: "Bob", UserId: "1002", UserImgHead: "http://82.157.179.66:8001/static/16e1041e5e02db1c77678084102a9b6b.jpeg"}, + {Username: "Charlie", UserId: "1003", UserImgHead: "http://82.157.179.66:8001/static/8944face68cc71bc452ea8a4fd0abc5b.jpeg"}, + } + + for i := 0; i < len(users); i++ { + service.LiveRoomService{}.SendTestPingLunNoStoage(liveRoomID, users[i].UserId, users[i].Username, users[i].UserImgHead, i+1) + } + + // 初始化礼物 ID 字符串数组(包含 5 个元素) + giftIds := [9]string{ + "1", + "n1/Dg1905sj1FyoBlQBvmbaDZFBNaKuKZH6zxHkv8Lg5x2cRfrKUTb8gzMs=", + "28rYzVFNyXEXFC8HI+f/WG+I7a6lfl3OyZZjUS+CVuwCgYZrPrUdytGHu0c=", + "fJs8HKQ0xlPRixn8JAUiL2gFRiLD9S6IFCFdvZODSnhyo9YN8q7xUuVVyZI=", + "PJ0FFeaDzXUreuUBZH6Hs+b56Jh0tQjrq0bIrrlZmv13GSAL9Q1hf59fjGk=", + "IkkadLfz7O/a5UR45p/OOCCG6ewAWVbsuzR/Z+v1v76CBU+mTG/wPjqdpfg=", + "gx7pmjQfhBaDOG2XkWI2peZ66YFWkCWRjZXpTqb23O/epru+sxWyTV/3Ufs=", + "pGLo7HKNk1i4djkicmJXf6iWEyd+pfPBjbsHmd3WcX0Ierm2UdnRR7UINvI=", + "P7zDZzpeO215SpUptB+aURb1+zC14UC9MY1+MHszKoF0p5gzYk8CNEbey60=", + } + + accScore := 0 + for { + if h.testSwitch == 0 { + break + } + for i := 0; i < len(users); i++ { + for j := 0; j < len(giftIds); j++ { + + giftInfo, err := manager.Get().GiftManager().GetGiftByID(giftIds[j]) + if err != nil { + } + + giftScore := giftInfo.Score + accScore = accScore + giftScore + service.LiveRoomService{}.SendTestGiftNoStoage(liveRoomID, users[i].UserId, users[i].Username, users[i].UserImgHead, + giftIds[j], 1, i+1, accScore) + + time.Sleep(10 * time.Millisecond) + } + } + } + + return +} + +// 发送批量请求关闭 +func (h *HttpController) CloseSendManyRequest(c *gin.Context) { + var req models.GiftRequestPayloadArr + 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 + } + + h.testSwitch = 0 + + // 返回处理结果(根据业务需求调整返回结构) + c.JSON(http.StatusOK, gin.H{ + "code": 0, + "message": "success", + "data": gin.H{}, + }) + +} + // 示例:获取用户信息的HTTP处理 func (h *HttpController) finishGame(c *gin.Context) { var req FinishGameRequest @@ -197,6 +405,11 @@ func (h *HttpController) finishGame(c *gin.Context) { if err != nil { fmt.Println("stop dou yin live room all task err : ", err, ", room id : ", roomId) } + + err = service.DouYinService{}.SyncGameStatusToDouYinService(roomId, 2, req.FinishTrackInfo) + if err != nil { + fmt.Println("sync game status end to dou yin err : ", err, ", room id : ", roomId) + } } // 返回处理结果(根据业务需求调整返回结构) diff --git a/app/controller/indexController.go b/app/controller/indexController.go index 771b948a17760a47eaa47685d1cde525f1a801c7..60170a89ab0af0886e3d5ecf67631c2e6a90717d 100644 --- a/app/controller/indexController.go +++ b/app/controller/indexController.go @@ -124,6 +124,16 @@ func (i *IndexController) Regist(ctx *gin.Context) { manager.Get().ConnectionManager().Register(conn, liveRoomUserInfo.RoomId, liveRoomUserInfo.AnchorOpenId) + // TODO + liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(liveRoomUserInfo.RoomId) + if err == nil { + if liveRoomInfo.State == "start" { + service.DouYinService{}.StartDouYinLiveRoomAllTask(liveRoomUserInfo.RoomId) + } + } else { + fmt.Println("get live room err : ", err) + } + headImgArr := []string{ "http://82.157.179.66:8001/static/03763e7c5fd77d3ba9d0ed2b35f5bfeb.jpeg", "http://82.157.179.66:8001/static/16e1041e5e02db1c77678084102a9b6b.jpeg", @@ -191,6 +201,14 @@ func (i *IndexController) HandleStartGameMessage(conn *websocket.Conn, msg Messa if err != nil { fmt.Println("start dou yin live room all task err : ", err, ", room id : ", liveRoomID) } + + var finishTrackInfo []models.FinishTrackInfo + // status 为1是开始 + err = service.DouYinService{}.SyncGameStatusToDouYinService(liveRoomID, 1, finishTrackInfo) + if err != nil { + fmt.Println("sync game status start to dou yin err : ", err, ", room id : ", liveRoomID) + } + } // 创建一个开始游戏的事件 diff --git a/app/manager/douyin/dy_service_manager.go b/app/manager/douyin/dy_service_manager.go index 7726b652302fb623017c3fe153832935b6227bb6..e466fd4a732b0644dc38aee6ba5e1b41c01f3b26 100644 --- a/app/manager/douyin/dy_service_manager.go +++ b/app/manager/douyin/dy_service_manager.go @@ -130,10 +130,12 @@ func StartDouYinLiveRoomAllTask(accessToken string, liveRoomId string) (err erro //1. 评论:live_comment //2. 礼物:live_gift //3. 点赞:live_like" + //4. 粉丝团:live_fansclub" const liveCommentType = "live_comment" const LiveGiftType = "live_gift" const LiveLikeType = "live_like" + const LiveFansType = "live_fansclub" err = StartDouYinLiveRoomSingleTask(accessToken, liveRoomId, liveCommentType) if err != nil { @@ -156,6 +158,13 @@ func StartDouYinLiveRoomAllTask(accessToken string, liveRoomId string) (err erro } fmt.Println("直播间", liveRoomId, " 已经开通点赞推送") + err = StartDouYinLiveRoomSingleTask(accessToken, liveRoomId, LiveFansType) + if err != nil { + fmt.Println("直播间", liveRoomId, " 开启粉丝团推送出错 : ", err) + + } + fmt.Println("直播间", liveRoomId, " 已经开通粉丝团推送") + return nil } @@ -210,10 +219,12 @@ func StopDouYinLiveRoomAllTask(accessToken string, liveRoomId string) (err error //1. 评论:live_comment //2. 礼物:live_gift //3. 点赞:live_like" + //4. 粉丝团:live_fansclub" const liveCommentType = "live_comment" const LiveGiftType = "live_gift" const LiveLikeType = "live_like" + const LiveFansType = "live_fansclub" err = StopDouYinLiveRoomSingleTask(accessToken, liveRoomId, liveCommentType) if err != nil { @@ -234,6 +245,12 @@ func StopDouYinLiveRoomAllTask(accessToken string, liveRoomId string) (err error } fmt.Println("直播间", liveRoomId, " 已经关闭点赞推送") + err = StopDouYinLiveRoomSingleTask(accessToken, liveRoomId, LiveFansType) + if err != nil { + fmt.Println("直播间", liveRoomId, " 关闭粉丝团推送出错 : ", err) + } + fmt.Println("直播间", liveRoomId, " 已经关闭粉丝团推送") + return nil } @@ -281,6 +298,102 @@ func StopDouYinLiveRoomSingleTask(accessToken string, liveRoomId string, taskTyp return nil } +// SyncGameStatusToDouYin 同步对局状态给抖音 +func SyncGameStatusToDouYin(accessToken string, anchorOpenId string, liveRoomId string, times int, startTime int64, endTime int64, status int, resultList []models.SyncGameGroupResultToDouYinBody) (err error) { + apiURL := config.Get().Douyin.APIWebcastBaseURL + "/api/gaming_con/round/sync_status" // 沙盒环境 + + // 构建请求参数 + requestBody := struct { + AnchorOpenId string `json:"anchor_open_id"` + Appid string `json:"appid"` + RoomId string `json:"roomid"` + RoundId int64 `json:"round_id"` + StartTime int64 `json:"start_time"` // 本局开始时间,秒级时间戳 + EndTime int64 `json:"end_time"` // 本局结束时间,秒级时间戳。同步的对局状态为对局结束时,该字段必传。 + Status int `json:"status"` // 当前房间的游戏对局状态(1=已开始、2=已结束) + GroupResultList []models.SyncGameGroupResultToDouYinBody `json:"group_result_list"` + }{ + AnchorOpenId: anchorOpenId, + Appid: config.Get().Douyin.AppID, + RoomId: liveRoomId, + RoundId: int64(times), + StartTime: startTime, + EndTime: endTime, + Status: status, + GroupResultList: resultList, + } + + // 设置请求头 + headers := map[string]string{ + "content-type": "application/json", + "X-Token": accessToken, + } + + // 定义响应结构 + var response struct { + ErrNo int `json:"errcode"` + ErrMsg string `json:"errmsg"` + } + + // 发送请求 + if err := utils.Post(apiURL, requestBody, headers, &response); err != nil { + return fmt.Errorf("请求失败: %w", err) + } + + // 处理错误码 + if response.ErrNo != 0 { + return fmt.Errorf("抖音接口错误[%d]: %s", response.ErrNo, response.ErrMsg) + } + + fmt.Println("同步抖音直播间 状态 : ", status, ", 直播id : ", liveRoomId, " , 成功") + return nil +} + +// SyncUserGroupToDouYin 同步用户选择阵营给抖音 +func SyncUserGroupToDouYin(accessToken string, liveRoomId string, times int, groupId string, openId string) (err error) { + apiURL := config.Get().Douyin.APIWebcastBaseURL + "/api/gaming_con/round/upload_user_group_info" // 沙盒环境 + + // 构建请求参数 + requestBody := struct { + Appid string `json:"appid"` + GroupId string `json:"group_id"` + OpenId string `json:"open_id"` + RoomId string `json:"roomid"` + RoundId int64 `json:"round_id"` + }{ + Appid: config.Get().Douyin.AppID, + GroupId: groupId, + OpenId: openId, + RoomId: liveRoomId, + RoundId: int64(times), + } + + // 设置请求头 + headers := map[string]string{ + "content-type": "application/json", + "X-Token": accessToken, + } + + // 定义响应结构 + var response struct { + ErrNo int `json:"errcode"` + ErrMsg string `json:"errmsg"` + } + + // 发送请求 + if err := utils.Post(apiURL, requestBody, headers, &response); err != nil { + return fmt.Errorf("请求失败: %w", err) + } + + // 处理错误码 + if response.ErrNo != 0 { + return fmt.Errorf("抖音接口错误[%d]: %s", response.ErrNo, response.ErrMsg) + } + + fmt.Println("同步抖音直播间 用户 : ", openId, ", 阵营 : ", groupId, ", 直播id : ", liveRoomId, " , 成功") + return nil +} + func GetDouYinRoomInfo(accessToken, clientToken string) (*models.LiveRoomUserInfo, error) { apiURL := config.Get().Douyin.APIWebcastBaseURL + "/api/webcastmate/info" diff --git a/app/manager/gift_manager.go b/app/manager/gift_manager.go index f5f3a577519dae51cf54a236af4a029c0c45a963..a22109ef5a9592ef75dd2bf616dfe652872c4778 100644 --- a/app/manager/gift_manager.go +++ b/app/manager/gift_manager.go @@ -19,6 +19,8 @@ type GiftManager struct { // 定义全局的gift列表 var giftList = []Gift{ {ID: "1", Name: "点赞", Value: 0, Score: 1, UpgradeLimit: 999999}, + {ID: "2", Name: "加入粉丝团", Value: 10, Score: 75, UpgradeLimit: 999999}, + {ID: "3", Name: "粉丝团升级", Value: 100, Score: 750, UpgradeLimit: 999999}, {ID: "n1/Dg1905sj1FyoBlQBvmbaDZFBNaKuKZH6zxHkv8Lg5x2cRfrKUTb8gzMs=", Name: "仙女棒", Value: 10, Score: 75, UpgradeLimit: 66}, {ID: "eplFUy7i0B0fiv0Iym1MpOZa5XmUE8g/WUAyJ6Tc+UJJDpcs7pzclNOz/WM=", Name: "黄色仙女棒", Value: 10, Score: 75, UpgradeLimit: 66}, {ID: "4I66OIE1HKWfM7PNvAHtAgYUSNlggSEgcpo3ai8GYQXAWqjrDuH8NtjsWEQ=", Name: "蓝色仙女棒", Value: 10, Score: 75, UpgradeLimit: 66}, diff --git a/app/manager/level_manager.go b/app/manager/level_manager.go index 27852d88c9b994061aa289cdfe701675d4b0fa87..ec8702363be96c1035cd0adcfa623d200d5dfada 100644 --- a/app/manager/level_manager.go +++ b/app/manager/level_manager.go @@ -16,14 +16,16 @@ type LevelManager struct { // 定义全局的gift列表 var levelList = []LevelSet{ - {Level: 1, UpperLimit: 1000, LevelGift: "1_ji_li_wu"}, // 1.3元 - {Level: 2, UpperLimit: 3000, LevelGift: "2_ji_li_wu"}, // 3.9元 - {Level: 3, UpperLimit: 5000, LevelGift: "3_ji_li_wu"}, // 6.66元 - {Level: 4, UpperLimit: 80000, LevelGift: "4_ji_li_wu"}, // 106.7元 - {Level: 5, UpperLimit: 300000, LevelGift: "5_ji_li_wu"}, // 400元 - {Level: 6, UpperLimit: 675000, LevelGift: "6_ji_li_wu"}, // 900元 - {Level: 7, UpperLimit: 1500000, LevelGift: "7_ji_li_wu"}, // 2000元 - {Level: 8, UpperLimit: 3800000, LevelGift: "8_ji_li_wu"}, // 5066元 + {Level: 1, UpperLimit: 1000, LevelGift: "1_ji_li_wu"}, // 1.3元 + {Level: 2, UpperLimit: 3000, LevelGift: "2_ji_li_wu"}, // 3.9元 + {Level: 3, UpperLimit: 5000, LevelGift: "3_ji_li_wu"}, // 6.66元 + {Level: 4, UpperLimit: 80000, LevelGift: "4_ji_li_wu"}, // 106.7元 + {Level: 5, UpperLimit: 300000, LevelGift: "5_ji_li_wu"}, // 400元 + {Level: 6, UpperLimit: 675000, LevelGift: "6_ji_li_wu"}, // 900元 + {Level: 7, UpperLimit: 1500000, LevelGift: "7_ji_li_wu"}, // 2000元 + {Level: 8, UpperLimit: 3800000, LevelGift: "8_ji_li_wu"}, // 5066元 + {Level: 9, UpperLimit: 6050000, LevelGift: "9_ji_li_wu"}, // 8066元 + {Level: 10, UpperLimit: 11275000, LevelGift: "10_ji_li_wu"}, // 15033元 } // NewLevelManager 初始化LevelManager diff --git a/app/manager/live_room_mamanger.go b/app/manager/live_room_mamanger.go index e4ce4c9707ac7e34079fcdf27e0608e6670ef8ba..47b75185fa1b3f1b14b951455edea2687f46bb3e 100644 --- a/app/manager/live_room_mamanger.go +++ b/app/manager/live_room_mamanger.go @@ -27,6 +27,8 @@ type LiveRoomInfo struct { NickName string `json:"nick_name"` FailGiftPageNum int `json:"fail_gift_page_num"` FailGiftWholePage int `json:"fail_gift_whole_page"` + StartAt sql.NullTime `json:"start_at"` // 使用 NullTime + EndAt sql.NullTime `json:"end_at"` // 使用 NullTime CreateAt sql.NullTime `json:"create_at"` // 使用 NullTime UpdateAt sql.NullTime `json:"update_at"` // 使用 NullTime } @@ -106,9 +108,9 @@ func (lrm *LiveRoomManager) CreateLiveRoomIfNotExist(liveRoomID, AnchorOpenId, A } // SetLiveRoomStatus 设置直播间的状态 -func (lrm *LiveRoomManager) JoinLiveRoomCamp(liveRoomID string, userId string, track int) error { +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, userId, track) + _, err := lrm.storage.JoinLiveRoomTrackMysql(liveRoomId, times, state, userId, track) if err != nil { return err } @@ -120,8 +122,8 @@ func (lrm *LiveRoomManager) JoinLiveRoomCamp(liveRoomID string, userId string, t defer lrm.mu.Unlock() // 如果不存在,则初始化一个新的状态 - if _, exists := lrm.roomUserTrack[liveRoomID][userId]; !exists { - lrm.roomUserTrack[liveRoomID][userId] = UserTrack{Track: track} + if _, exists := lrm.roomUserTrack[liveRoomId][userId]; !exists { + lrm.roomUserTrack[liveRoomId][userId] = UserTrack{Track: track} } return nil @@ -160,6 +162,8 @@ func (lrm *LiveRoomManager) GetLiveInfo(liveRoomID string) (*LiveRoomInfo, error LiveRoomId: liveMysqlInfo.LiveRoomId, 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 de866bb3dd9a701b6ccfca5af107653f22540648..faa2561cb92a91403fa255142cc132c24a288360 100644 --- a/app/manager/live_room_mysql_storage.go +++ b/app/manager/live_room_mysql_storage.go @@ -18,6 +18,8 @@ type LiveRoomMysqlInfo struct { AnchorOpenId string `db:"anchor_open_id"` AvatarUrl string `db:"avatar_url"` NickName string `db:"nick_name"` + StartAt sql.NullTime `db:"start_at"` // 使用 NullTime + EndAt sql.NullTime `db:"end_at"` // 使用 NullTime CreateAt sql.NullTime `db:"create_at"` // 使用 NullTime UpdateAt sql.NullTime `db:"update_at"` // 使用 NullTime } @@ -182,14 +184,29 @@ func (lrm *LiveRoomMysqlStorage) GetLiveRoom(liveRoomID string) (*LiveRoomMysqlI // SetLiveRoomstate 设置直播间的状态 func (lrm *LiveRoomMysqlStorage) SetLiveRoom(liveRoomID string, state string, times int) error { - _, err := db.GetDB().Exec(` + query := "" + if state == "start" { + query = ` update live_room set state = ?, times = ?, + start_at = CURRENT_TIMESTAMP, update_at = CURRENT_TIMESTAMP where live_room_id = ? - `, + ` + } else if state == "end" { + query = ` + update live_room + set state = ?, + times = ?, + end_at = CURRENT_TIMESTAMP, + update_at = CURRENT_TIMESTAMP + where + live_room_id = ? + ` + } + _, err := db.GetDB().Exec(query, state, times, liveRoomID) // 更新值参数 if err != nil { @@ -249,24 +266,23 @@ func (lrm *LiveRoomMysqlStorage) GetLiveTrackByUserId(liveRoomId string, userId } // 设置直播间用户参加阵营的数据 -func (lrm *LiveRoomMysqlStorage) JoinLiveRoomTrackMysql(liveRoomId string, userId string, track int) (*LiveTrackUserMysqlInfo, error) { - liveRoomMysqlInfo, err := lrm.GetLiveRoom(liveRoomId) - - if err != nil { - return nil, fmt.Errorf("join live room track error : %v, by no live room", err) +func (lrm *LiveRoomMysqlStorage) JoinLiveRoomTrackMysql(liveRoomId string, times int, state string, userId string, track int) (*LiveTrackUserMysqlInfo, error) { + //liveRoomMysqlInfo, err := lrm.GetLiveRoom(liveRoomId) + //if err != nil { + // return nil, fmt.Errorf("join live room track error : %v, by no live room", err) + //} + + if state == "end" { + return nil, fmt.Errorf("join live room track error because live room state is end") } - if liveRoomMysqlInfo.State == "end" { - return nil, fmt.Errorf("join live room track error : %v, by live room state is end", err) - } - - liveTrackUserMysqlInfo, err := lrm.GetLiveTrackByUserId(liveRoomId, userId, liveRoomMysqlInfo.Times) + liveTrackUserMysqlInfo, err := lrm.GetLiveTrackByUserId(liveRoomId, userId, times) if err == nil { return liveTrackUserMysqlInfo, fmt.Errorf("user has join live room track ") } - err = lrm.CreateLiveTrack(liveRoomId, userId, liveRoomMysqlInfo.Times, track) + err = lrm.CreateLiveTrack(liveRoomId, userId, times, track) if err != nil { return nil, fmt.Errorf("failed to initialize user live track: %v", err) } diff --git a/app/models/models.go b/app/models/models.go index 476b05c7acc2139b30addafb5677389775f776c2..a416bcb639369213dddb3100b4c293ee25c91a79 100644 --- a/app/models/models.go +++ b/app/models/models.go @@ -163,3 +163,42 @@ type LikeOneRequest struct { type LikeRequest struct { Arr []LikeOneRequest `json:"arr"` } + +// 抖音推送数据的点赞元数据 +type FansOneRequest struct { + MsgID string `json:"msg_id"` + SecOpenID string `json:"sec_openid"` + AvatarURL string `json:"avatar_url"` + Nickname string `json:"nickname"` + Timestamp int64 `json:"timestamp"` + FansClubLevel int `json:"fansclub_level"` // 用户粉丝团等级,加团消息下默认传1 + FansClubReasonType int `json:"fansclub_reason_type"` // 粉丝团消息类型:1-升级,2-加团 +} + +// 抖音推送数据的点赞元数据 +type FansRequest struct { + Arr []FansOneRequest `json:"arr"` +} + +// 抖音推送数据的点赞元数据 +type SyncGameGroupResultToDouYinBody struct { + GroupId string `json:"group_id"` // 阵营id,red, green, yellow + Result int `json:"result"` // 对局结果(1=胜利、2=失败、3=平局) +} + +// 抖音查询观众阵营的数据结构 +type DouYinGetUserGroupRequest struct { + AppId string `json:"app_id"` + OpenId string `json:"open_id"` + RoomId string `json:"room_id"` +} + +// 抖音推送观众选择阵营的数据结构 +type DouYinPushUserGroupRequest struct { + AppId string `json:"app_id"` + OpenId string `json:"open_id"` + RoomId string `json:"room_id"` + GroupId string `json:"group_id"` + AvatarUrl string `json:"avatar_url"` + NickName string `json:"nickname"` +} diff --git a/app/service/douyin_service.go b/app/service/douyin_service.go index 741f4f95854cf206ed1f66b00f86237b5fcf8834..d316cb709355a721753c1c8a4aff33e83e9bbc7f 100644 --- a/app/service/douyin_service.go +++ b/app/service/douyin_service.go @@ -56,6 +56,65 @@ func (ls DouYinService) StopDouYinLiveRoomAllTask(liveRoomId string) error { } return nil } + +func (ls DouYinService) SyncGameStatusToDouYinService(liveRoomId string, status int, FinishTrackInfo []models.FinishTrackInfo) error { + token, err := ls.GetToken() + if err != nil { + return err + } + + liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(liveRoomId) + loc, _ := time.LoadLocation("Asia/Shanghai") + + startTime := int64(0) + endTime := int64(0) + var resultList []models.SyncGameGroupResultToDouYinBody + + if status == 1 { + startTime = time.Now().In(loc).Unix() + } else { + startTime = liveRoomInfo.StartAt.Time.UnixMilli() + endTime = liveRoomInfo.EndAt.Time.UnixMilli() + for _, info := range FinishTrackInfo { + gameResult := 3 + if info.IsChampion == 1 { + gameResult = 1 + } else if info.IsFinish == 1 { + gameResult = 2 + } else { + gameResult = 3 + } + result := models.SyncGameGroupResultToDouYinBody{ + GroupId: string(info.Track), + Result: gameResult, + } + + resultList = append(resultList, result) + } + } + + err = douyin.SyncGameStatusToDouYin(token, liveRoomInfo.AnchorOpenId, liveRoomId, liveRoomInfo.Times, startTime, endTime, status, resultList) + if err != nil { + return err + } + return nil +} + +func (ls DouYinService) SyncUserGroupToDouYinService(liveRoomId string, times int, groupId string, openId string) error { + token, err := ls.GetToken() + if err != nil { + return err + } + + //liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(liveRoomId) + + err = douyin.SyncUserGroupToDouYin(token, liveRoomId, times, groupId, openId) + if err != nil { + return err + } + return nil +} + func (ls DouYinService) RequestDouYinForLiveLogin(liveRoomToken string) (models.LiveRoomUserInfo, error) { if liveRoomToken == "this@is*Test" { return models.LiveRoomUserInfo{ diff --git a/app/service/live_room_service.go b/app/service/live_room_service.go index e26f5b1ad241f186fcb2c649bb7fa2d76b31d644..782234cdd8e809866351a0818d3b1534316ae029 100644 --- a/app/service/live_room_service.go +++ b/app/service/live_room_service.go @@ -14,7 +14,12 @@ import ( type LiveRoomService struct{} func (ls LiveRoomService) OneUserJoinTrack(liveRoomID string, userId string, track int) error { - err := manager.Get().LiveRoomManager().JoinLiveRoomCamp(liveRoomID, userId, track) + liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(liveRoomID) + if err != nil { + return fmt.Errorf("want join track but get live info error: %v, by no live room", err) + } + + err = manager.Get().LiveRoomManager().JoinLiveRoomCamp(liveRoomID, liveRoomInfo.Times, liveRoomInfo.State, userId, track) if err != nil { return err @@ -36,6 +41,13 @@ func (ls LiveRoomService) OneUserJoinTrack(liveRoomID string, userId string, tra UserScore = userInfo.Score } + if liveRoomID != utils.TestRoomId { + err := DouYinService{}.SyncUserGroupToDouYinService(liveRoomID, liveRoomInfo.Times, string(track), userId) + if err != nil { + fmt.Println("sync user group status end to dou yin err : ", err, ", room id : ", liveRoomID) + } + } + // 创建一个礼物事件 data := models.LiveEventData{ Event: "broad_join_track", @@ -82,6 +94,54 @@ func (ls LiveRoomService) OneUserJoinTrack(liveRoomID string, userId string, tra return nil } +func (ls LiveRoomService) SendTestPingLunNoStoage(liveRoomID string, userId, userName, userHeadImg string, track int) error { + now := time.Now() + // 创建一个礼物事件 + 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: userId, + Type: "broad_join_track", + Content: strconv.Itoa(track), + Camp: track, + SecGiftID: "n1/Dg1905sj1FyoBlQBvmbaDZFBNaKuKZH6zxHkv8Lg5x2cRfrKUTb8gzMs=", + GiftNum: 2, + GiftValue: 10, + Name: "", + Nickname: userName, + Level: 1, + AvatarURL: userHeadImg, + UserScore: 123, + Timestamp: now.UnixMilli(), + }, + } + + //i.eventManager.AddEventData(liveRoomID, data) + manager.Get().EventManager().AddEventData(liveRoomID, data) + return nil +} + func (ls LiveRoomService) OneUserSendGift(msgID string, liveRoomID string, userId string, giftId string, giftNum int) error { // 1、获取直播间状态 liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(liveRoomID) @@ -224,6 +284,69 @@ func (ls LiveRoomService) OneUserSendGift(msgID string, liveRoomID string, userI fmt.Println(liveRoomID, "号直播间,收货礼物广播事件 已 add") return nil } + +func (ls LiveRoomService) SendTestGiftNoStoage(liveRoomID string, userId, userName, userHeadImg string, giftId string, giftNum int, track, accGiftScore int) error { + + now := time.Now() + + giftInfo, err := manager.Get().GiftManager().GetGiftByID(giftId) + if err != nil { + return fmt.Errorf("can not find gift by giftId , err : %v", err) + } + + giftName := giftInfo.Name + giftValue := giftInfo.Value + giftScore := giftInfo.Score + + // 创建一个礼物事件 + 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: userId, + Type: "live_gift", + Camp: track, + SecGiftID: giftId, + GiftNum: giftNum, + GiftValue: giftValue, + Name: giftName, + Nickname: userName, + Level: 1, + AccGiftScore: accGiftScore, + AvatarURL: userHeadImg, + UserScore: giftScore, + GiftLevel: 1, + GiftUpgrading: 0, + GameScore: accGiftScore, + Timestamp: now.UnixMilli(), + }, + } + + //i.eventManager.AddEventData(liveRoomID, data) + manager.Get().EventManager().AddEventData(liveRoomID, data) + fmt.Println(liveRoomID, "号直播间,收货礼物广播事件 已 add") + return nil +} func (ls LiveRoomService) FinishGame(msgID string, liveRoomId string, finishTrackInfos []models.FinishTrackInfo, timestamp int) ([]models.LiveRoomResult, error) { // 获取直播间信息 liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(liveRoomId) @@ -322,17 +445,17 @@ func (ls LiveRoomService) FinishGame(msgID string, liveRoomId string, finishTrac } trackBiggestMap := make(map[int]trackBiggestRecord) for _, giftRecord := range giftRecordList { - liveRoomTotalScore += giftRecord.Score + liveRoomTotalScore += giftRecord.TotalScore if championTrack == giftRecord.Track { - liveRoomChampionTrackTotalScore += giftRecord.Score + liveRoomChampionTrackTotalScore += giftRecord.TotalScore } else if utils.Exists(finishTrackArr, giftRecord.Track) { - liveRoomOtherFinishTrackTotalScore += giftRecord.Score + liveRoomOtherFinishTrackTotalScore += giftRecord.TotalScore } // 将礼物记录记录到每个UserId的礼物积分总数 if scoreRecord, exists := liveRoomUserScoreRecord[giftRecord.UserId]; exists { liveRoomUserScoreRecord[giftRecord.UserId] = userScoreRecord{ - Value: scoreRecord.Value + giftRecord.Value, - Score: scoreRecord.Score + giftRecord.Score, + Value: scoreRecord.Value + giftRecord.TotalValue, + Score: scoreRecord.Score + giftRecord.TotalScore, Track: giftRecord.Track, UserName: giftRecord.UserName, HeadImg: giftRecord.UserHeadImg, @@ -343,8 +466,8 @@ func (ls LiveRoomService) FinishGame(msgID string, liveRoomId string, finishTrac } else { // 如果 userId 不存在,直接初始化 Score liveRoomUserScoreRecord[giftRecord.UserId] = userScoreRecord{ - Value: giftRecord.Value, - Score: giftRecord.Score, + Value: giftRecord.TotalValue, + Score: giftRecord.TotalScore, Track: giftRecord.Track, UserName: giftRecord.UserName, HeadImg: giftRecord.UserHeadImg, diff --git a/main.go b/main.go index ca10cef5058970972a15a4c13715e8624e0b19a2..0556318d73033498c0722e3c5dfaa921b64b2360 100644 --- a/main.go +++ b/main.go @@ -20,7 +20,7 @@ import ( func main() { // 1. 定义并解析命令行参数 var env string - flag.StringVar(&env, "env", "prod", "运行环境(dev/prod)") + flag.StringVar(&env, "env", "dev", "运行环境(dev/prod)") flag.Parse() env = strings.ToLower(env) // 统一转为小写 diff --git a/templates/index.html b/templates/index.html index 3675bac5530eb1511b2d4e5a8465486fe8f914a4..5625439c09c82f0e4f5ff502c488c366cb2cc81e 100644 --- a/templates/index.html +++ b/templates/index.html @@ -55,12 +55,16 @@ + +

+ +

@@ -93,12 +97,19 @@

- + + +
+
+
+ + +


- +

@@ -107,6 +118,8 @@ + +