diff --git a/api/consts/option.go b/api/consts/option.go index c2d8a88f..1a5374f4 100644 --- a/api/consts/option.go +++ b/api/consts/option.go @@ -105,3 +105,7 @@ const ( Notification_ObjType_AllStreamerAndUser = 2 Notification_ObjType_Customized = 3 ) + +const ( + Notification_PushTime_Instant = 0 // 即时推送 +) diff --git a/api/errcode/errcode.go b/api/errcode/errcode.go index 7573c00c..b3839633 100644 --- a/api/errcode/errcode.go +++ b/api/errcode/errcode.go @@ -247,9 +247,10 @@ var ErrCodeMsgMap = map[ErrCode]string{ ErrCodeVideoModerationSrvFail: "视频审核服务错误", ErrCodeVideoModerationNotExist: "视频审核不存在", - ErrCodeNotificationSrvFail: "系统通知表服务错误", - ErrCodeNotificationNotExist: "系统通知表不存在", - ErrCodeNotificationCountRedisCacheInvalid: "系统通知表redis缓存失效", + ErrCodeNotificationSrvFail: "系统通知表服务错误", + ErrCodeNotificationNotExist: "系统通知表不存在", + ErrCodeNotificationPushFail: "系统通知表推送失败", + ErrCodeNotificationPullFail: "系统通知表拉取失败", ErrCodeRavenIQTestSrvFail: "瑞文智商测试表服务错误", ErrCodeRavenIQTestNotExist: "瑞文智商测试表不存在", @@ -592,10 +593,11 @@ const ( ErrCodeVideoModerationNotExist ErrCode = -44002 // 视频审核不存在 // Notification: 46xxx - ErrCodeNotificationSrvOk ErrCode = ErrCodeOk - ErrCodeNotificationSrvFail ErrCode = -46001 // 系统通知表服务错误 - ErrCodeNotificationNotExist ErrCode = -46002 // 系统通知表不存在 - ErrCodeNotificationCountRedisCacheInvalid ErrCode = -46003 // 系统通知表redis缓存失效 + ErrCodeNotificationSrvOk ErrCode = ErrCodeOk + ErrCodeNotificationSrvFail ErrCode = -46001 // 系统通知表服务错误 + ErrCodeNotificationNotExist ErrCode = -46002 // 系统通知表不存在 + ErrCodeNotificationPushFail ErrCode = -46003 // 系统通知表推送失败 + ErrCodeNotificationPullFail ErrCode = -46004 // 系统通知表拉取失败 // Media: 60xxx ErrCodeMediaSrvOk ErrCode = ErrCodeOk diff --git a/api/proto/notification/proto/notification_api.go b/api/proto/notification/proto/notification_api.go index f56fb3d6..d1d43ffa 100644 --- a/api/proto/notification/proto/notification_api.go +++ b/api/proto/notification/proto/notification_api.go @@ -6,47 +6,32 @@ import ( ) // op 列表 -type ApiListUnreadByMidReq struct { +type ApiListByMidReq struct { base.BaseRequest Offset int `json:"offset"` Limit int `json:"limit"` } -type ApiListUnreadByMidData struct { +type ApiListByMidData struct { List []*dbstruct.Notification `json:"list"` Offset int `json:"offset"` More int `json:"more"` } -type ApiListUnreadByMidResp struct { +type ApiListByMidResp struct { base.BaseResponse - Data *ApiListUnreadByMidData `json:"data"` + Data *ApiListByMidData `json:"data"` } -// op 列表 -type ApiCountUnreadByMidReq struct { +// op 接收 +type ApiReceiveReq struct { base.BaseRequest } -type ApiCountUnreadByMidData struct { - UnreadCount int64 `json:"unread_count"` +type ApiReceiveData struct { } -type ApiCountUnreadByMidResp struct { +type ApiReceiveResp struct { base.BaseResponse - Data *ApiCountUnreadByMidData `json:"data"` -} - -// op 更新 -type ApiReadReq struct { - base.BaseRequest - Ids []int64 -} - -type ApiReadData struct { -} - -type ApiReadResp struct { - base.BaseResponse - Data *ApiReadData `json:"data"` + Data *ApiReceiveData `json:"data"` } diff --git a/api/proto/notification/proto/notification_op.go b/api/proto/notification/proto/notification_op.go index 01d3a98b..f18c0de8 100644 --- a/api/proto/notification/proto/notification_op.go +++ b/api/proto/notification/proto/notification_op.go @@ -9,8 +9,6 @@ import ( type OpCreateReq struct { base.BaseRequest *dbstruct.Notification - ObjType *int64 `json:"obj_type"` // 通知接收人类型 - ObjMids []int64 `json:"obj_mids"` // 通知接收人mids } type OpCreateData struct { @@ -53,7 +51,6 @@ type OpUpdateResp struct { type OpListByMidReq struct { base.BaseRequest Uid *int64 `json:"mid"` - IsRead *int64 `json:"is_read"` Offset int `json:"offset"` Limit int `json:"limit"` } diff --git a/app/mix/controller/init.go b/app/mix/controller/init.go index 82935d2c..54f82b38 100644 --- a/app/mix/controller/init.go +++ b/app/mix/controller/init.go @@ -298,9 +298,7 @@ func Init(r *gin.Engine) { // 系统通知表 apiNotificationGroup := r.Group("/api/notification", PrepareToC()) - apiNotificationGroup.POST("list_unread_by_mid", middleware.JSONParamValidator(notificationproto.ApiListUnreadByMidReq{}), middleware.JwtAuthenticator(), ApiGetUnreadNotificationListByMid) - apiNotificationGroup.POST("read", middleware.JSONParamValidator(notificationproto.ApiReadReq{}), middleware.JwtAuthenticator(), ApiReadNotification) - apiNotificationGroup.POST("get_unread_count_by_mid", middleware.JSONParamValidator(notificationproto.ApiCountUnreadByMidReq{}), middleware.JwtAuthenticator(), ApiGetUnreadNotificationCountByMid) + apiNotificationGroup.POST("list_by_mid", middleware.JSONParamValidator(notificationproto.ApiListByMidReq{}), middleware.JwtAuthenticator(), ApiGetNotificationListByMid) // =============================== 以下是服务,只允许内网调用 =============================== diff --git a/app/mix/controller/notification_api.go b/app/mix/controller/notification_api.go index 62b24572..1a84ae98 100644 --- a/app/mix/controller/notification_api.go +++ b/app/mix/controller/notification_api.go @@ -11,22 +11,22 @@ import ( "github.com/gin-gonic/gin" ) -func ApiGetUnreadNotificationListByMid(ctx *gin.Context) { - req := ctx.MustGet("client_req").(*notificationproto.ApiListUnreadByMidReq) +func ApiGetNotificationListByMid(ctx *gin.Context) { + req := ctx.MustGet("client_req").(*notificationproto.ApiListByMidReq) //设置默认页长 if req.Limit == 0 { req.Limit = consts.DefaultPageSize } - list, ec := service.DefaultService.ApiGetUnreadNotificationListByMid(ctx, req) + list, ec := service.DefaultService.ApiGetNotificationListByMid(ctx, req) if ec != errcode.ErrCodeNotificationSrvOk { - logger.Error("ApiGetUnreadNotificationListByMid fail, req: %v, ec: %v", util.ToJson(req), ec) + logger.Error("ApiGetNotificationListByMid fail, req: %v, ec: %v", util.ToJson(req), ec) ReplyErrCodeMsg(ctx, ec) return } - data := ¬ificationproto.ApiListUnreadByMidData{ + data := ¬ificationproto.ApiListByMidData{ List: list, Offset: req.Offset + len(list), } @@ -35,31 +35,3 @@ func ApiGetUnreadNotificationListByMid(ctx *gin.Context) { } ReplyOk(ctx, data) } - -func ApiGetUnreadNotificationCountByMid(ctx *gin.Context) { - req := ctx.MustGet("client_req").(*notificationproto.ApiCountUnreadByMidReq) - - unreadCount, ec := service.DefaultService.ApiGetUnreadNotificationCountByMid(ctx, req) - if ec != errcode.ErrCodeNotificationSrvOk { - logger.Error("ApiGetUnreadNotificationCountByMid fail, req: %v, ec: %v", util.ToJson(req), ec) - ReplyErrCodeMsg(ctx, ec) - return - } - - data := ¬ificationproto.ApiCountUnreadByMidData{ - UnreadCount: unreadCount, - } - ReplyOk(ctx, data) -} - -func ApiReadNotification(ctx *gin.Context) { - req := ctx.MustGet("client_req").(*notificationproto.ApiReadReq) - ec := service.DefaultService.ApiReadNotification(ctx, req) - if ec != errcode.ErrCodeNotificationSrvOk { - logger.Error("ApiReadNotification fail, req: %v, ec: %v", util.ToJson(req), ec) - ReplyErrCodeMsg(ctx, ec) - return - } - - ReplyOk(ctx, nil) -} diff --git a/app/mix/service/apiservice.go b/app/mix/service/apiservice.go index bca59bac..4190eef8 100644 --- a/app/mix/service/apiservice.go +++ b/app/mix/service/apiservice.go @@ -4257,11 +4257,13 @@ func (s *Service) ApiGetRavenIQTestList(ctx *gin.Context, req *Raven_IQ_testprot } // Notification -func (s *Service) ApiGetUnreadNotificationListByMid(ctx *gin.Context, req *notificationproto.ApiListUnreadByMidReq) (list []*dbstruct.Notification, ec errcode.ErrCode) { +func (s *Service) ApiGetNotificationListByMid(ctx *gin.Context, req *notificationproto.ApiListByMidReq) (list []*dbstruct.Notification, ec errcode.ErrCode) { ec = errcode.ErrCodeNotificationSrvOk + + // 查询得到已经拉取到的 + list, err := _DefaultNotification.OpListByMid(ctx, ¬ificationproto.OpListByMidReq{ - Uid: goproto.Int64(req.BaseRequest.Mid), - IsRead: goproto.Int64(consts.Notification_NotRead), + Uid: goproto.Int64(req.BaseRequest.Mid), }) if err != nil { logger.Error("ApiGetNotificationList fail, req: %v, err: %v", util.ToJson(req), err) @@ -4270,3 +4272,41 @@ func (s *Service) ApiGetUnreadNotificationListByMid(ctx *gin.Context, req *notif } return } + +func (s *Service) ApiReceiveAllBcstedNotifs(ctx *gin.Context, req *notificationproto.ApiReceiveReq) (ec errcode.ErrCode) { + ec = errcode.ErrCodeNotificationSrvOk + + // 查询账户获取角色 + acct, err := _DefaultAccount.OpListByMid(ctx, &accountproto.OpListByMidReq{ + Mid: goproto.Int64(req.BaseRequest.Mid), + }) + if acct == nil { + ec = errcode.ErrCodeAccountNotExist + return + } + if err != nil { + logger.Error("OpListByMid fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeAccountSrvFail + return + } + + // 用户、主播、准主播才需拉取消息 + if !util.Int64Contains([]int64{consts.Streamer, consts.StreamerToBe, consts.User}, acct.GetRole()) { + return + } + + objType := consts.Notification_ObjType_AllStreamer + if acct.GetRole() == consts.User { + objType = consts.Notification_ObjType_AllUser + } + + // 拉取消息 + err = DefaultNotifBcstCenter.ReceiveAllBcstedNotifs(ctx, req.BaseRequest.Mid, int64(objType)) + if err != nil { + logger.Error("ReceiveAllBcstedNotifs fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeNotificationPullFail + return + } + + return +} diff --git a/app/mix/service/notification_center.go b/app/mix/service/notification_center.go index 088faeaa..2bf4a7b7 100644 --- a/app/mix/service/notification_center.go +++ b/app/mix/service/notification_center.go @@ -6,6 +6,7 @@ import ( "service/library/logger" "github.com/gin-gonic/gin" + goproto "google.golang.org/protobuf/proto" ) var DefaultNotifBcstCenter *NotifBcstCenter @@ -17,8 +18,49 @@ func NewNotifBcstCenter() *NotifBcstCenter { return new(NotifBcstCenter) } +// 对外接口 +func (s *NotifBcstCenter) BcstNotifs(ctx *gin.Context, nids []int64, objType int64, objMids []int64) error { + var err error + switch objType { + case consts.Notification_ObjType_AllStreamer: + err = s.bcstNotifsToAll(ctx, nids, objType) + case consts.Notification_ObjType_AllUser: + err = s.bcstNotifsToAll(ctx, nids, objType) + case consts.Notification_ObjType_AllStreamerAndUser: + err = s.bcstNotifsToAll(ctx, nids, consts.Notification_ObjType_AllStreamer) + if err != nil { + break + } + err = s.bcstNotifsToAll(ctx, nids, consts.Notification_ObjType_AllUser) + case consts.Notification_ObjType_Customized: + err = s.pushNotifsToMids(ctx, nids, objMids) + default: + return nil + } + + // 更新推送状态 + if err != nil { + logger.Error("Broadcast notifs fail, err: %v", err) + err = _DefaultNotification.OpUpdateByIds(ctx, &dbstruct.Notification{ + Status: goproto.Int64(consts.Notification_FailedToPush), + }, nids) + if err != nil { + logger.Error("_DefaultNotification OpUpdateByIds fail, err: %v", err) + } + return err + } + err = _DefaultNotification.OpUpdateByIds(ctx, &dbstruct.Notification{ + Status: goproto.Int64(consts.Notification_Pushed), + }, nids) + if err != nil { + logger.Error("_DefaultNotification OpUpdateByIds fail, err: %v", err) + return err + } + return nil +} + // 写入一条全局广播消息 -func (s *NotifBcstCenter) BcstANotif(ctx *gin.Context, objType int64, nids []int64) error { +func (s *NotifBcstCenter) bcstNotifsToAll(ctx *gin.Context, nids []int64, objType int64) error { // 获取最新的主播/用户方广播版本号 notifBcstVers, err := _DefaultNotifBcstVers.GetAndUpdateNotifBcstVers(ctx, objType) if err != nil { @@ -39,9 +81,9 @@ func (s *NotifBcstCenter) BcstANotif(ctx *gin.Context, objType int64, nids []int } // 直接推送至用户 -func (s *NotifBcstCenter) PushNotifsToMids(ctx *gin.Context, nids []int64, mids []int64) error { +func (s *NotifBcstCenter) pushNotifsToMids(ctx *gin.Context, nids []int64, objMids []int64) error { notifReceives := make([]*dbstruct.NotifReceive, 0) - for _, mid := range mids { + for _, mid := range objMids { for _, nid := range nids { notifReceives = append(notifReceives, &dbstruct.NotifReceive{ ObjMid: mid, diff --git a/app/mix/service/service.go b/app/mix/service/service.go index 6de4a617..b21e6e89 100644 --- a/app/mix/service/service.go +++ b/app/mix/service/service.go @@ -3094,7 +3094,7 @@ func (s *Service) OpCreateContactCustomerService(ctx *gin.Context, req *contact_ _, err := redis.GetRedisClient().Incr(logic.GetCreateContactCustomerServiceCountIdForRedis(req.ContactCustomerService.GetSessionId(), consts.ContactCustomerService_FromSupportor)) if err != nil { logger.Error("Redis Incr fail, req: %v, err: %v", util.ToJson(req), err) - ec = errcode.ErrCodeNotificationCountRedisCacheInvalid + ec = errcode.ErrCodeContactCustomerServiceCountRedisCacheInvalid return } @@ -5021,12 +5021,22 @@ func (s *Service) OpCreateNotification(ctx *gin.Context, req *notificationproto. req.Notification.Status = goproto.Int64(consts.Notification_Created) err := _DefaultNotification.OpCreate(ctx, req) if err != nil { - logger.Error("OpCreate fail, req: %v, err: %v", util.ToJson(req), err) + logger.Error("_DefaultNotification OpCreate fail, req: %v, err: %v", util.ToJson(req), err) ec = errcode.ErrCodeNotificationSrvFail return } - // 根据推送时间判断,若即时推送,则直接进入消息中心推送 + // 根据推送时间判断,若即时推送,则直接进入消息中心推送,否则不作处理 + if req.Notification.GetPushTime() == consts.Notification_PushTime_Instant { + nids := []int64{req.Notification.GetId()} + objType := util.DerefInt64(req.Notification.ObjType) + err = DefaultNotifBcstCenter.BcstNotifs(ctx, nids, objType, req.Notification.ObjMids) + if err != nil { + logger.Error("BcstNotifs fail, req: %v, err: %v", util.ToJson(req), err) + ec = errcode.ErrCodeNotificationPushFail + return + } + } return } diff --git a/dbstruct/notification.go b/dbstruct/notification.go index 911e5ac0..b7f3b716 100644 --- a/dbstruct/notification.go +++ b/dbstruct/notification.go @@ -3,6 +3,8 @@ package dbstruct type Notification struct { Id *int64 `json:"id" bson:"_id"` // 系统通知表id SubMid *int64 `json:"sub_mid" bson:"sub_mid"` // 通知发送人mid + ObjType *int64 `json:"obj_type" bson:"obj_type"` // 通知接收人类型 + ObjMids []int64 `json:"obj_mids" bson:"obj_mids"` // 通知接收人mids NType *int64 `json:"n_type" bson:"n_type"` // 消息类型 NDesc *string `json:"n_desc" bson:"n_desc"` // 消息描述 Message *string `json:"message" bson:"message"` // 消息内容 @@ -17,6 +19,20 @@ type Notification struct { DelFlag *int64 `json:"del_flag" bson:"del_flag"` // 删除标记 } +func (p *Notification) GetId() int64 { + if p != nil && p.Id != nil { + return *p.Id + } + return 0 +} + +func (p *Notification) GetPushTime() int64 { + if p != nil && p.PushTime != nil { + return *p.PushTime + } + return 0 +} + type NotifBcst struct { Id int64 `json:"id" bson:"_id"` // 通知广播表id Nids []int64 `json:"nids" bson:"nids"` // 系统通知表ids