diff --git a/api/consts/notif_template.go b/api/consts/notif_template.go index b6a76dc8..ce550f97 100644 --- a/api/consts/notif_template.go +++ b/api/consts/notif_template.go @@ -30,9 +30,12 @@ const ( AudNotifTemp_NameChangeApplied = 1732523339 // 用户修改昵称 AudNotifTemp_NamePassed = 1732523340 // 用户修改昵称成功(todo) AudNotifTemp_NameRollbacked = 1732523341 // 用户修改昵称被驳回(todo) - AudNotifTemp_StreamerBasicInfoApplied = 1732523342 // 提交申请入驻材料 - AudNotifTemp_StreamerBasicInfoPassed = 1732523343 // 运营后台审核通过申请入驻 - AudNotifTemp_StreamerBasicInfoRejected = 1732523344 // 运营后台审核未通过申请入驻 + AudNotifTemp_StreamerBasicInfoApplied = 1732523342 // 提交达人入驻材料 + AudNotifTemp_StreamerBasicInfoPassed = 1732523343 // 运营后台审核通过达人入驻 + AudNotifTemp_StreamerBasicInfoRejected = 1732523344 // 运营后台审核未通过达人入驻 + AudNotifTemp_GuildRegistrationApplied = 1733900290 // 提交公会入驻材料 + AudNotifTemp_GuildRegistrationPassed = 1733900291 // 运营后台审核通过公会入驻 + AudNotifTemp_GuildRegistrationRejected = 1733900292 // 运营后台审核未通过公会入驻 AudNotifTemp_StreamerDetailsApplied = 1732523345 // 提交完善资料材料 AudNotifTemp_StreamerDetailsPassed = 1732523346 // 运营后台审核通过完善资料 AudNotifTemp_StreamerDetailsRejected = 1732523347 // 运营后台审核写上备注并未通过完善资料 diff --git a/api/consts/regexp.go b/api/consts/regexp.go new file mode 100644 index 00000000..b3adbed5 --- /dev/null +++ b/api/consts/regexp.go @@ -0,0 +1,6 @@ +package consts + +const ( + AppHyperlinkRegexp = "app_hyperlink" + H5HyperlinkRegexp = "h5_hyperlink" +) diff --git a/app/mix/service/notif_builder_handler.go b/app/mix/service/notif_builder_handler.go index 3641c399..23265993 100644 --- a/app/mix/service/notif_builder_handler.go +++ b/app/mix/service/notif_builder_handler.go @@ -3,6 +3,7 @@ package service import ( "service/api/consts" "service/api/interfaces" + accountproto "service/api/proto/account/proto" accountpunishmentproto "service/api/proto/accountpunishment/proto" streamerproto "service/api/proto/streamer/proto" zoneproto "service/api/proto/zone/proto" @@ -238,6 +239,7 @@ func (handler *NotifBuilderHandler) handleSysZoneCreated() { argsMap := make(map[string]any) argsMap["thumbnail"] = preview argsMap["build_hyperlink"] = DefaultService.utilBuildInwardHyperLink + argsMap["hyperlink_params_map"] = util.NewHyperLinkParamsMapBuilder().NewEnds("app", "h5").WriteParamToAllEnd("mid", zone.GetMid()).Map() DefaultService.utilWriteNotifInfoByMap(ctx, consts.SysNotifTemp_ZoneCreated, zone.GetMid(), argsMap) } @@ -304,9 +306,11 @@ func (handler *NotifBuilderHandler) handleAudStreamerBasicInfoPassed() { func (handler *NotifBuilderHandler) handleAudStreamerBasicInfoRejected() { handler.handlerMap[consts.AudNotifTemp_StreamerBasicInfoRejected] = func(ctx *gin.Context, args ...any) { mids := args[0].([]int64) - remarks := args[1].(string) for _, mid := range mids { - DefaultService.utilWriteNotifInfo(ctx, consts.AudNotifTemp_StreamerBasicInfoRejected, mid, remarks) + argsMap := make(map[string]any) + argsMap["build_hyperlink"] = DefaultService.utilBuildInwardHyperLink + + DefaultService.utilWriteNotifInfoByMap(ctx, consts.AudNotifTemp_StreamerBasicInfoRejected, mid, argsMap) } } } @@ -332,7 +336,11 @@ func (handler *NotifBuilderHandler) handleAudStreamerDetailsRejected() { mids := args[0].([]int64) remarks := args[1].(string) for _, mid := range mids { - DefaultService.utilWriteNotifInfo(ctx, consts.AudNotifTemp_StreamerDetailsRejected, mid, remarks) + argsMap := make(map[string]any) + argsMap["template_params"] = []any{remarks} + argsMap["build_hyperlink"] = DefaultService.utilBuildInwardHyperLink + + DefaultService.utilWriteNotifInfoByMap(ctx, consts.AudNotifTemp_StreamerDetailsRejected, mid, argsMap) } } } @@ -485,6 +493,24 @@ func (handler *NotifBuilderHandler) handleAudMomentRejected() { handler.handlerMap[consts.AudNotifTemp_MomentRejected] = func(ctx *gin.Context, args ...any) { moment := args[0].(*dbstruct.Moment) ctStr := util.FormatTsAsNotifT(moment.GetCt()) + + // 获取缩略图 + preview := &dbstruct.MediaComponent{} + if len(moment.MediaComp.GetImageIds()) > 0 { // 取首图 + imageIds := moment.MediaComp.GetImageIds() + preview.ImageIds = util.Int64Slice([]int64{imageIds[0]}) + } else if len(moment.MediaComp.GetVideoIds()) > 0 { // 取封面 + mediaFillables := make([]mediafiller.MediaFillable, 0) + mediaFillables = append(mediaFillables, moment.MediaComp) + coverIds, _ := mediafiller.GetCoverIds(ctx, mediaFillables) + preview.ImageIds = util.Int64Slice(coverIds) + } + + argsMap := make(map[string]any) + argsMap["template_params"] = []any{ctStr} + argsMap["thumbnail"] = preview + argsMap["build_hyperlink"] = DefaultService.utilBuildInwardHyperLink + argsMap["hyperlink_params_map"] = util.NewHyperLinkParamsMapBuilder().NewEnds("app", "h5").WriteParamToAllEnd("id", moment.GetId()).Map() DefaultService.utilWriteNotifInfo(ctx, consts.AudNotifTemp_MomentRejected, moment.GetMid(), ctStr) } } @@ -540,6 +566,7 @@ func (handler *NotifBuilderHandler) handleAudZoneMomentRejected() { argsMap["template_params"] = []any{ctStr, cTypeDesc, mTypeDesc, remarks} argsMap["thumbnail"] = preview argsMap["build_hyperlink"] = DefaultService.utilBuildInwardHyperLink + argsMap["hyperlink_params_map"] = util.NewHyperLinkParamsMapBuilder().NewEnds("app", "h5").WriteParamToAllEnd("id", zonemoment.GetId()).Map() DefaultService.utilWriteNotifInfoByMap(ctx, consts.AudNotifTemp_ZoneMomentRejected, zonemoment.GetMid(), argsMap) } @@ -594,6 +621,7 @@ func (handler *NotifBuilderHandler) handleAudZoneMomentReeditionRejected() { argsMap["template_params"] = []any{ctStr, cTypeDesc, mTypeDesc, remarks} argsMap["thumbnail"] = preview argsMap["build_hyperlink"] = DefaultService.utilBuildInwardHyperLink + argsMap["hyperlink_params_map"] = util.NewHyperLinkParamsMapBuilder().NewEnds("app", "h5").WriteParamToAllEnd("id", zonemoment.GetId()).Map() DefaultService.utilWriteNotifInfoByMap(ctx, consts.AudNotifTemp_ZoneMomentReeditionRejected, zonemoment.GetMid(), argsMap) } @@ -637,11 +665,14 @@ func (handler *NotifBuilderHandler) handleVasZoneSuperfanshipPurchased_User() { handler.handlerMap[consts.VasNotifTemp_ZoneSuperfanshipPurchased_User] = func(ctx *gin.Context, args ...any) { order := args[0].(*dbstruct.Order) streamer, _ := _DefaultStreamer.OpListByMid(ctx, &streamerproto.OpListByMidReq{Mid: goproto.Int64(order.GetUid())}) + streamerAcct, _ := _DefaultAccount.OpListByMid(ctx, &accountproto.OpListByMidReq{Mid: goproto.Int64(order.GetUid())}) argsMap := make(map[string]any) - argsMap["template_params"] = util.FormatTsAsNotifT(order.GetSuperfanshipUntil()) + argsMap["template_params"] = []any{streamerAcct.GetName(), util.FormatTsAsNotifT(order.GetSuperfanshipUntil())} argsMap["thumbnail"] = streamer.Album argsMap["build_hyperlink"] = DefaultService.utilBuildInwardHyperLink + argsMap["hyperlink_params_map"] = util.NewHyperLinkParamsMapBuilder().NewEnds("app", "h5").WriteParamToAllEnd("mid", order.GetUid()).Map() + argsMap["link_text_template_params"] = []any{streamerAcct.GetName()} DefaultService.utilWriteNotifInfoByMap(ctx, consts.VasNotifTemp_ZoneSuperfanshipPurchased_User, order.GetMid(), argsMap) } diff --git a/app/mix/service/service.go b/app/mix/service/service.go index df2651fd..2b44090a 100644 --- a/app/mix/service/service.go +++ b/app/mix/service/service.go @@ -76,6 +76,7 @@ import ( "service/library/payclients/wxpaycli" "service/library/payclients/yeepaycli" "service/library/redis" + "service/library/regexpcli" "strconv" "strings" "time" @@ -217,6 +218,7 @@ func (s *Service) Init(c any) (err error) { } yeepaycli.Init(cfg.Yeepay) + regexpcli.Init() s.cron = cron.NewCron(store) @@ -2099,7 +2101,7 @@ func (s *Service) OpApproveStreamerAuthApprovalBasic(ctx *gin.Context, req *stre // 发送通知 DefaultNotifBuilderHandler.Handle(ctx)( - consts.AudNotifTemp_StreamerBasicInfoRejected)(mids, util.DerefString(req.Remarks)) + consts.AudNotifTemp_StreamerBasicInfoRejected)(mids) return } diff --git a/app/mix/service/utilservice.go b/app/mix/service/utilservice.go index 605bbcdf..3a4de801 100644 --- a/app/mix/service/utilservice.go +++ b/app/mix/service/utilservice.go @@ -36,10 +36,12 @@ import ( "service/library/mediafiller" "service/library/mycrypto" "service/library/redis" + "service/library/regexpcli" "service/library/validator" "strings" "time" + "github.com/dlclark/regexp2" "github.com/gin-gonic/gin" "github.com/qiniu/qmgo" "go.mongodb.org/mongo-driver/mongo" @@ -2299,7 +2301,12 @@ func (s *Service) utilWriteNotifInfoByMap(ctx *gin.Context, notifTempId int64, o buildHyperLink, ok := mp["build_hyperlink"] if ok { - notifBuilder.BuildHyperLink = buildHyperLink.(func(ctx *gin.Context, frontendRouteId int64) ([]*dbstruct.NotifHyperlink, error)) + notifBuilder.BuildHyperLink = buildHyperLink.(func(ctx *gin.Context, frontendRouteId int64, argsMap map[string]map[string]any) ([]*dbstruct.NotifHyperlink, error)) + } + + hyperLinkParamsMap, ok := mp["hyperlink_params_map"] + if ok { + notifBuilder.HyperLinkParamsMap = hyperLinkParamsMap.(map[string]map[string]any) } notifBuilders = append(notifBuilders, notifBuilder) @@ -2327,7 +2334,8 @@ func (s *Service) utilCalcAccountPunishmentEndNotifTime(acctpunishment *dbstruct return notifTime, nil } -func (s *Service) utilBuildInwardHyperLink(ctx *gin.Context, frontendRouteId int64) ([]*dbstruct.NotifHyperlink, error) { +func (s *Service) utilBuildInwardHyperLink(ctx *gin.Context, frontendRouteId int64, + argsMap map[string]map[string]any) ([]*dbstruct.NotifHyperlink, error) { // 获取跳转路径 frontendroute, err := _DefaultFrontendRoute.GetById(ctx, frontendRouteId) @@ -2336,16 +2344,35 @@ func (s *Service) utilBuildInwardHyperLink(ctx *gin.Context, frontendRouteId int return make([]*dbstruct.NotifHyperlink, 0), err } + // 将跳转路径的占位符替换 + appRoute, err := regexpcli.GetRegexp(consts.AppHyperlinkRegexp).ReplaceFunc( + frontendroute.GetAppRoutePath(), func(m regexp2.Match) string { + return fmt.Sprint(argsMap["app"][m.Groups()[1].String()]) + }, -1, -1) + if err != nil { + logger.Error("regexp2 ReplaceFunc fail, err: %v", err) + return make([]*dbstruct.NotifHyperlink, 0), err + } + + h5Route, err := regexpcli.GetRegexp(consts.H5HyperlinkRegexp).ReplaceFunc( + frontendroute.GetAppRoutePath(), func(m regexp2.Match) string { + return fmt.Sprintf("%v%v", m.String(), argsMap["h5"][m.Groups()[2].String()]) + }, -1, -1) + if err != nil { + logger.Error("regexp2 ReplaceFunc fail, err: %v", err) + return make([]*dbstruct.NotifHyperlink, 0), err + } + hyperlinks := make([]*dbstruct.NotifHyperlink, 0) hyperlinks = append(hyperlinks, &dbstruct.NotifHyperlink{ Action: goproto.String(consts.FrontendRouteAction_Inward), - Params: frontendroute.AppRoutePath, + Params: goproto.String(appRoute), }) hyperlinks = append(hyperlinks, &dbstruct.NotifHyperlink{ Action: goproto.String(consts.FrontendRouteAction_Inward), - Params: frontendroute.H5RoutePath, + Params: goproto.String(h5Route), }) return hyperlinks, nil diff --git a/bizcommon/util/builder.go b/bizcommon/util/builder.go new file mode 100644 index 00000000..461c359c --- /dev/null +++ b/bizcommon/util/builder.go @@ -0,0 +1,39 @@ +package util + +type HyperlinkParamsMapBuilder struct { + mp map[string]map[string]any +} + +func NewHyperLinkParamsMapBuilder() *HyperlinkParamsMapBuilder { + return &HyperlinkParamsMapBuilder{ + mp: make(map[string]map[string]any), + } +} + +func (builder *HyperlinkParamsMapBuilder) NewEnd(end string) *HyperlinkParamsMapBuilder { + builder.mp[end] = make(map[string]any) + return builder +} + +func (builder *HyperlinkParamsMapBuilder) NewEnds(ends ...string) *HyperlinkParamsMapBuilder { + for _, end := range ends { + builder.mp[end] = make(map[string]any) + } + return builder +} + +func (builder *HyperlinkParamsMapBuilder) WriteParam(end, key string, value any) *HyperlinkParamsMapBuilder { + builder.mp[end][key] = value + return builder +} + +func (builder *HyperlinkParamsMapBuilder) WriteParamToAllEnd(key string, value any) *HyperlinkParamsMapBuilder { + for _, mp := range builder.mp { + mp[key] = value + } + return builder +} + +func (builder *HyperlinkParamsMapBuilder) Map() map[string]map[string]any { + return builder.mp +} diff --git a/dbstruct/notification.go b/dbstruct/notification.go index 7b736058..ea915d1a 100644 --- a/dbstruct/notification.go +++ b/dbstruct/notification.go @@ -127,17 +127,18 @@ type NotifRecentReceive struct { } type NotifBuilder struct { - TemplateId int64 // 模板id - TemplateParams []any // 模板参数 - ObjMids []int64 // 目标Mids - ObjType int64 // 目标类型 - LinkTextTemplateParams []any // 链接模板参数 - Thumbnail *MediaComponent // 缩略图 - HyperLinks []*NotifHyperlink // 超链接数组 - PushTime int64 // 推送时间 - SetNid func(ctx *gin.Context, nid int64) error // nid存储函数,一般用于取消推送 - GetNid func() int64 // nid访问器 - BuildHyperLink func(ctx *gin.Context, frontendRouteId int64) ([]*NotifHyperlink, error) // 超链接组装函数 + TemplateId int64 // 模板id + TemplateParams []any // 模板参数 + ObjMids []int64 // 目标Mids + ObjType int64 // 目标类型 + LinkTextTemplateParams []any // 链接模板参数 + Thumbnail *MediaComponent // 缩略图 + HyperLinks []*NotifHyperlink // 超链接数组 + PushTime int64 // 推送时间 + SetNid func(ctx *gin.Context, nid int64) error // nid存储函数,一般用于取消推送 + GetNid func() int64 // nid访问器 + BuildHyperLink func(ctx *gin.Context, frontendRouteId int64, argsMap map[string]map[string]any) ([]*NotifHyperlink, error) // 超链接组装函数 + HyperLinkParamsMap map[string]map[string]any // 超链接参数map } // 消息内超链接信息 diff --git a/library/middleware/notif_sender.go b/library/middleware/notif_sender.go index 54673d5e..2301dc4d 100644 --- a/library/middleware/notif_sender.go +++ b/library/middleware/notif_sender.go @@ -174,7 +174,7 @@ func AssembleNotification(ctx *gin.Context, notifBuilder *dbstruct.NotifBuilder) if len(notifBuilder.HyperLinks) > 0 { hyperlinks = notifBuilder.HyperLinks } else if notifBuilder.BuildHyperLink != nil && cfg.FrontendRouteId > 0 { - hyperlinks, err = notifBuilder.BuildHyperLink(ctx, cfg.FrontendRouteId) + hyperlinks, err = notifBuilder.BuildHyperLink(ctx, cfg.FrontendRouteId, notifBuilder.HyperLinkParamsMap) if err != nil { logger.Error("BuildHyperLink fail, err: %v", err) } diff --git a/library/regexpcli/client.go b/library/regexpcli/client.go new file mode 100644 index 00000000..b1d1d615 --- /dev/null +++ b/library/regexpcli/client.go @@ -0,0 +1,25 @@ +package regexpcli + +import ( + "service/api/consts" + + "github.com/dlclark/regexp2" +) + +var defaultRegexpClient *Client + +type Client struct { + regexpMap map[string]*regexp2.Regexp +} + +func Init() { + defaultRegexpClient = new(Client) + + defaultRegexpClient.regexpMap = make(map[string]*regexp2.Regexp) + defaultRegexpClient.regexpMap[consts.AppHyperlinkRegexp] = regexp2.MustCompile(`\[(.*?)\]`, 0) + defaultRegexpClient.regexpMap[consts.H5HyperlinkRegexp] = regexp2.MustCompile(`(\?|&)(.*?)=`, 0) +} + +func GetRegexp(str string) *regexp2.Regexp { + return defaultRegexpClient.regexpMap[str] +}