package imctrl import ( "fmt" "91porn-server/app/service/customerser" "net/http" "91porn-server/app/middleware/authuser" "91porn-server/app/service/imser" "91porn-server/app/service/messageser" "91porn-server/common" "91porn-server/common/imclient" "91porn-server/common/log" "91porn-server/common/stderr" "91porn-server/common/truthutil" "91porn-server/models/v/messagemod" "91porn-server/models/v/sourcemod" "github.com/gin-gonic/gin" ) var accepts = []int32{1000, 1001, 1002, 1003} const ( live_default = "ys-01" faqURL = "/kefu/api/faq/queryByAppId" checkURL = "/kefu/api/play/unread" ) // GetImSign doc // @Summary 获取Im签名 // @Description 获取Im签名 // @Tags IM // @Accept mpfd,json // @Produce json,html // @Success 200 {string} json "{"msg": "操作成功"}" // @Failure 400 {string} json "{"msg": "操作失败"}" // @Router /api/im/sign [get] func GetImSign(ctx *gin.Context) { token := ctx.Request.Header.Get("Authorization") //为兼容H5带APP token if token == "" { ctx.AbortWithStatusJSON(http.StatusOK, stderr.ErrNoToken.Struct()) return } claims, err := authuser.ParseToken(token) if err != nil { log.Error("GetImSign ParseToken error", log.Any("token", fmt.Sprintf("%+v", token)), log.E(err)) ctx.JSON(http.StatusBadRequest, stderr.InvalidToken.Struct()) return } ua, _ := common.GetUA(ctx) if !sourcemod.GetCustomerStat() { common.ServeJSON(ctx, stderr.ErrCustomerBanned, nil) return } sign := imser.GetSign(claims.UID, ua) common.ServeJSON(ctx, stderr.Success, sign) } // GetImSign doc // @Summary 获取Im签名 // @Description 获取Im签名 b 不需要token校验 // @Tags IM // @Accept mpfd,json // @Produce json,html // @Success 200 {string} json "{"msg": "操作成功"}" // @Failure 400 {string} json "{"msg": "操作失败"}" // @Router /api/im/whiteSign [get] func GetWhiteImSign(ctx *gin.Context) { if !sourcemod.GetCustomerStat() { common.ServeJSON(ctx, stderr.ErrCustomerBanned, nil) return } var uid uint64 var sign string ua, _ := common.GetUA(ctx) token := ctx.Request.Header.Get("Authorization") //token if token != "" { claims, err := authuser.ParseToken(token) if err != nil { log.Error("GetImSign ParseToken error", log.Any("token", fmt.Sprintf("%+v", token)), log.E(err)) } uid = claims.UID } if uid != 0 { //sign = imser.GetSign(uid, ua) res, err := customerser.GetUrl(uid, ua) if err != nil { log.Error("GetImSign GetUrl error", log.Any("uid", uid), log.E(err)) common.ServeJSON(ctx, stderr.Failure, nil) return } sign = "/app/newkefu?" + res.Data.Params } else if sign == "" { sign = imser.GetWhiteSign() } common.ServeJSON(ctx, stderr.Success, sign) } // ImSign doc // @Summary 获取Im签名 // @Description 获取Im签名 b 不需要token校验 // @Tags IM // @Accept mpfd,json // @Produce json,html // @Success 200 {string} json "{"msg": "操作成功"}" // @Failure 400 {string} json "{"msg": "操作失败"}" // @Router /api/im/newSign [get] func ImSign(ctx *gin.Context) { if !sourcemod.GetCustomerStat() { common.ServeJSON(ctx, stderr.ErrCustomerBanned, nil) return } var uid uint64 var sign string ua, _ := common.GetUA(ctx) token := ctx.Request.Header.Get("Authorization") //token if token != "" { claims, err := authuser.ParseToken(token) if err != nil { log.Error("GetImSign ParseToken error", log.Any("token", fmt.Sprintf("%+v", token)), log.E(err)) } else { uid = claims.UID } } if uid != 0 { sign = imser.GetSignNew(uid, ua) } else if sign == "" { sign = imser.GetWhiteSignNew() } common.ServeJSON(ctx, stderr.Success, gin.H{ "sign": sign, "faq": faqURL, "check": checkURL, "isVoiceActive": true, }) } func Token(ctx *gin.Context) { uid, err := common.GetUID(ctx) if err != nil { common.ServeJSON(ctx, stderr.ErrNoToken, err) return } if !imser.SDKEnabled() { common.ServeJSON(ctx, stderr.Success, &imser.SDKAuthInfo{ Enabled: false, UserID: uid, }) return } data, err := imser.GetSDKAuth(uid) if err != nil { log.Warn("Get IM SDK token error", log.Any("uid", uid), log.E(err)) common.ServeJSON(ctx, stderr.Failure, nil) return } if ua, uaErr := common.GetUA(ctx); uaErr == nil { data.SysType = ua.SysType } common.ServeJSON(ctx, stderr.Success, data) } type UserIDReq struct { UserID uint64 `json:"userId"` ImUserID int64 `json:"imUserId"` } type UserIDResp struct { Enabled bool `json:"enabled"` UserID uint64 `json:"userId"` ImUserID int64 `json:"imUserId"` } func UserID(ctx *gin.Context) { if _, err := common.GetUID(ctx); err != nil { common.ServeJSON(ctx, stderr.ErrNoToken, err) return } var req UserIDReq if err := ctx.ShouldBindJSON(&req); err != nil { common.ServeJSON(ctx, stderr.ErrParamError, err) return } if (req.UserID > 0) == (req.ImUserID > 0) { common.ServeJSON(ctx, stderr.ErrParamError, nil) return } if !imser.SDKEnabled() { common.ServeJSON(ctx, stderr.Success, &UserIDResp{ Enabled: false, UserID: req.UserID, ImUserID: req.ImUserID, }) return } resp := &UserIDResp{Enabled: true, UserID: req.UserID, ImUserID: req.ImUserID} if req.UserID > 0 { imUserID, err := imser.ResolveStoredIMUserID(req.UserID) if err != nil { log.Warn("resolve IM user id failed", log.Any("uid", req.UserID), log.E(err)) common.ServeJSON(ctx, stderr.Failure, err.Error()) return } resp.ImUserID = imUserID } else { uid, err := imser.ResolveUIDByIMUserID(req.ImUserID) if err != nil { log.Warn("resolve user id failed", log.Any("imUserId", req.ImUserID), log.E(err)) common.ServeJSON(ctx, stderr.Failure, err.Error()) return } resp.UserID = uid } common.ServeJSON(ctx, stderr.Success, resp) } type EnsureFriendReq struct { PeerID uint64 `json:"peerId" binding:"required"` } type EnsureFriendResp struct { Enabled bool `json:"enabled"` UserID uint64 `json:"userId"` ImUserID int64 `json:"imUserId"` PeerID uint64 `json:"peerId"` PeerImUserID int64 `json:"peerImUserId"` FriendAdded bool `json:"friendAdded"` } func EnsureFriend(ctx *gin.Context) { uid, err := common.GetUID(ctx) if err != nil { common.ServeJSON(ctx, stderr.ErrNoToken, err) return } var req EnsureFriendReq if err = ctx.ShouldBindJSON(&req); err != nil { common.ServeJSON(ctx, stderr.ErrParamError, err) return } if req.PeerID == 0 || req.PeerID == uid { common.ServeJSON(ctx, stderr.ErrParamError, nil) return } if !imser.SDKEnabled() { common.ServeJSON(ctx, stderr.Success, &EnsureFriendResp{ Enabled: false, UserID: uid, PeerID: req.PeerID, }) return } selfIMUserID, peerIMUserID, added, err := imser.EnsureFriendsBidirectional(uid, req.PeerID) if err != nil { log.Warn("ensure IM friend failed", log.Any("uid", uid), log.Any("peerId", req.PeerID), log.E(err)) common.ServeJSON(ctx, stderr.Failure, err.Error()) return } common.ServeJSON(ctx, stderr.Success, &EnsureFriendResp{ Enabled: true, UserID: uid, ImUserID: selfIMUserID, PeerID: req.PeerID, PeerImUserID: peerIMUserID, FriendAdded: added, }) } type FriendListReq struct { Now *int64 `json:"now,omitempty"` } type FriendListResp struct { Enabled bool `json:"enabled"` UserID uint64 `json:"userId"` ImUserID int64 `json:"imUserId"` Now int64 `json:"now"` NextNow int64 `json:"nextNow"` Friends []imser.IMFriendItem `json:"friends"` } func FriendList(ctx *gin.Context) { uid, err := common.GetUID(ctx) if err != nil { common.ServeJSON(ctx, stderr.ErrNoToken, err) return } var req FriendListReq _ = ctx.ShouldBindJSON(&req) if !imser.SDKEnabled() { common.ServeJSON(ctx, stderr.Success, &FriendListResp{ Enabled: false, UserID: uid, Friends: []imser.IMFriendItem{}, }) return } var now int64 if req.Now != nil { now = *req.Now } imUserID, usedNow, nextNow, friends, err := imser.FriendList(uid, now) if err != nil { log.Warn("get IM friend list failed", log.Any("uid", uid), log.E(err)) common.ServeJSON(ctx, stderr.Failure, err.Error()) return } common.ServeJSON(ctx, stderr.Success, &FriendListResp{ Enabled: true, UserID: uid, ImUserID: imUserID, Now: usedNow, NextNow: nextNow, Friends: friends, }) } type MessageHistoryReq struct { PeerID uint64 `json:"peerId" binding:"required"` StartTime *int64 `json:"startTime,omitempty"` EndTime *int64 `json:"endTime,omitempty"` StartSeq *int64 `json:"startSeq,omitempty"` EndSeq *int64 `json:"endSeq,omitempty"` Direction string `json:"direction,omitempty"` Size int `json:"size,omitempty"` } type MessageHistoryResp struct { Enabled bool `json:"enabled"` UserID uint64 `json:"userId"` ImUserID int64 `json:"imUserId"` PeerID uint64 `json:"peerId"` PeerImUserID int64 `json:"peerImUserId"` Messages []imser.IMHistoryMessage `json:"messages"` } func MessageHistory(ctx *gin.Context) { uid, err := common.GetUID(ctx) if err != nil { common.ServeJSON(ctx, stderr.ErrNoToken, err) return } var req MessageHistoryReq if err = ctx.ShouldBindJSON(&req); err != nil { common.ServeJSON(ctx, stderr.ErrParamError, err) return } if req.PeerID == 0 || req.PeerID == uid { common.ServeJSON(ctx, stderr.ErrParamError, nil) return } if !imser.SDKEnabled() { common.ServeJSON(ctx, stderr.Success, &MessageHistoryResp{ Enabled: false, UserID: uid, PeerID: req.PeerID, Messages: []imser.IMHistoryMessage{}, }) return } historyReq := imclient.HistoryMessageRequest{ Direction: req.Direction, Size: req.Size, } if req.StartTime != nil { historyReq.StartTime = *req.StartTime } if req.EndTime != nil { historyReq.EndTime = *req.EndTime } if req.StartSeq != nil { historyReq.StartSeq = *req.StartSeq } if req.EndSeq != nil { historyReq.EndSeq = *req.EndSeq } selfIMUserID, peerIMUserID, messages, err := imser.HistoryMessages(uid, req.PeerID, historyReq) if err != nil { log.Warn("get IM message history failed", log.Any("uid", uid), log.Any("peerId", req.PeerID), log.E(err)) common.ServeJSON(ctx, stderr.Failure, err.Error()) return } common.ServeJSON(ctx, stderr.Success, &MessageHistoryResp{ Enabled: true, UserID: uid, ImUserID: selfIMUserID, PeerID: req.PeerID, PeerImUserID: peerIMUserID, Messages: messages, }) } // SendMessage doc // @Summary IM 发送私信 // @Description 扣费 + 内容校验通过后,通过第三方 IM 平台投递;参数与 /app/message/priLetter/add 一致 // @Tags IM // @Accept json // @Produce json // @Param body body messagemod.AddMsgReqInfo true "私信参数" // @Success 200 {string} json "{"msg": "操作成功"}" // @Failure 400 {string} json "{"msg": "操作失败"}" // @Router /app/im/message/send [post] func SendMessage(ctx *gin.Context) { uid, err := common.GetUID(ctx) if err != nil { common.ServeJSON(ctx, stderr.ErrNoToken, err) return } var req messagemod.AddMsgReqInfo if err = ctx.ShouldBind(&req); err != nil { common.ServeJSON(ctx, stderr.ErrParamError, err) return } if len(req.ImgUrl) <= 0 && req.Content == "" { common.ServeJSON(ctx, stderr.ErrParamError, nil) return } // 内容合规校验:失败时静默成功(与 priLetter/add 行为一致,避免泄露规则) if req.Content != "" && !truthutil.CheckIsValid(req.Content, 1) { log.Error("IM 私信内容校验不通过", log.Any("uid", uid), log.Any("content", req.Content)) common.ServeJSON(ctx, stderr.Success, nil) return } code := messageser.SendIMPrivateLetter(uid, req) if code != stderr.Success { log.Warn("imctrl SendMessage fail", log.Any("uid", uid), log.Any("takeUid", req.TakeUid), log.Any("code", code)) common.ServeJSON(ctx, code, nil) return } common.ServeJSON(ctx, stderr.Success, nil) }