package middleware import ( "fmt" "service/apollostruct" "service/app/mix/service" "service/app/mix/service/logic" "service/dbstruct" "service/library/apollo" "service/library/logger" "service/api/consts" notificationproto "service/api/proto/notification/proto" goproto "google.golang.org/protobuf/proto" "github.com/gin-gonic/gin" ) var ( DefaultNotifSender gin.HandlerFunc ) func InitNotifSender(_DefaultNotification *logic.Notification, _DefaultNotifBcstVers *logic.NotifBcstVers, _DefaultNotifBcstCenter *service.NotifBcstCenter) { DefaultNotifSender = func(ctx *gin.Context) { // 获取通知builder notifBuildersObj, ok := ctx.Get("notif_builders") if !ok { return } notifBuilders := notifBuildersObj.([]*dbstruct.NotifBuilder) for _, notifBuilder := range notifBuilders { // 如果是取消推送,则更新推送状态为已取消 if CancelNotif(ctx, notifBuilder, _DefaultNotification) { continue } // 如果是同步广播版本号,则进行同步 if SyncNotifBcstVers(ctx, notifBuilder, _DefaultNotifBcstVers) { continue } // 组装通知 notification, err := AssembleNotification(notifBuilder) if err != nil { logger.Error("通知组装失败:%v", err) continue } // 创建通知 err = _DefaultNotification.OpCreate(ctx, ¬ificationproto.OpCreateReq{ Notification: notification, }) if err != nil { logger.Error("通知创建失败:%v", err) continue } // 将通知id暂存,若暂存失败,则不广播该条通知,因业务无法再控制其停止 if notifBuilder.SetNid != nil { err = notifBuilder.SetNid(ctx, notification.GetId()) if err != nil { logger.Error("通知id暂存失败:%v", err) continue } } nids := make([]int64, 0) nids = append(nids, notification.GetId()) // 广播通知 if notification.GetPushTime() == consts.Notification_PushTime_Instant { err = _DefaultNotifBcstCenter.BcstNotifs(ctx, nids, notification.GetObjType(), notification.ObjMids) if err != nil { logger.Error("通知广播失败:%v", err) continue } } } ctx.Next() } } func NotifSender() gin.HandlerFunc { return DefaultNotifSender } func CancelNotif(ctx *gin.Context, notifBuilder *dbstruct.NotifBuilder, notifService *logic.Notification) bool { if notifBuilder.TemplateId == consts.CtrlNotifTemp_CancelNotif { err := notifService.OpUpdate(ctx, ¬ificationproto.OpUpdateReq{ Notification: &dbstruct.Notification{ Id: goproto.Int64(notifBuilder.GetNid()), Status: goproto.Int64(consts.Notification_Cancelled), }, }) if err != nil { logger.Error("_DefaultNotification OpUpdate failed : %v", err) } return true } return false } func SyncNotifBcstVers(ctx *gin.Context, notifBuilder *dbstruct.NotifBuilder, notifBcstVersService *logic.NotifBcstVers) bool { objType := int64(-1) if notifBuilder.TemplateId == consts.CtrlNotifTemp_SyncNotifBcstVersForUser { objType = consts.Notification_ObjType_AllUser } else if notifBuilder.TemplateId == consts.CtrlNotifTemp_SyncNotifBcstVersForStreamer { objType = consts.Notification_ObjType_AllStreamer } if objType != -1 { // 获取当前主播/用户全局广播的版本号(注意这个版本号-1才是当前数据库有的最新版本号) notifBcstVers, err := notifBcstVersService.GetNotifBcstVers(ctx, objType) if err != nil { logger.Error("GetNotifBcstVers fail, err: %v", err) return true } // 获取该主播/用户已接收的全局广播版本号,并直接更新至最新的全局广播版本号 for _, mid := range notifBuilder.ObjMids { _, err = notifBcstVersService.GetAndUpdateNotifBcstReceiveVers(ctx, mid, notifBcstVers.Vers) if err != nil { logger.Error("GetAndUpdateNotifBcstReceiveVers fail, err: %v", err) return true } } return true } else { return false } } func AssembleNotification(notifBuilder *dbstruct.NotifBuilder) (*dbstruct.Notification, error) { notification := &dbstruct.Notification{} notification.SubMid = goproto.Int64(0) // 从模板Id拿到模板信息 key := fmt.Sprint(notifBuilder.TemplateId) cfg := apollostruct.NotifTemplateCfg{} err := apollo.GetJson(key, &cfg, apollo.ApolloOpts().SetNamespace("notif_template")) if err != nil { logger.Error("Apollo read failed : %v", err) return nil, err } // 通知接收人mids不为空则默认认为是自定义发送 if len(notifBuilder.ObjMids) > 0 { notification.ObjMids = notifBuilder.ObjMids notification.ObjType = goproto.Int64(consts.Notification_ObjType_Customized) } else { notification.ObjType = goproto.Int64(notifBuilder.ObjType) } // 消息类型 notification.NType = goproto.Int64(cfg.NType) notification.NDesc = goproto.String(consts.NotifDescMap[cfg.NType]) // 拼装通知信息 msg := fmt.Sprintf(cfg.NotifTemplate, notifBuilder.TemplateParams...) notification.Message = goproto.String(msg) // 链接信息 if notifBuilder.Action != "" { linkText := fmt.Sprintf(cfg.LinkTextTemplate, notifBuilder.LinkTextTemplateParams...) notification.LinkText = goproto.String(linkText) notification.Action = goproto.String(notifBuilder.Action) notification.Thumbnail = notifBuilder.Thumbnail notification.Params = goproto.String(notifBuilder.Params) } // 推送时间 notification.PushTime = goproto.Int64(notifBuilder.PushTime) return notification, nil }