package campaign import ( "joybuywork/internal/app" "joybuywork/internal/consts" "joybuywork/internal/repository/cache" "joybuywork/internal/repository/dbcheck" "joybuywork/internal/repository/finder" "joybuywork/internal/repository/model" "joybuywork/internal/repository/mtype" "joybuywork/internal/repository/withdefault" "joybuywork/internal/utils" "joybuywork/internal/utils/blink" "joybuywork/internal/utils/logic" pb "joybuywork/proto/go_proto/w_campaign" "joybuywork/proto/go_proto/workerr" "fmt" "strings" "time" dlinkpb "gits.branchcn.com/backend/deeplink/proto/go_proto/dlink" linkpb "gits.branchcn.com/backend/shortlink/proto/go_proto/link" ) type ChannelCreate struct { logic.Logic Req *pb.ChannelCreateReq Res *pb.ChannelCreateRes } func (s *ChannelCreate) Run() error { return logic.Run(s) } func (s *ChannelCreate) Exec() (err error) { cpn, project, err := s.campaign() if err != nil { return } defer s.afterDone(cpn) if s.Req.GetCType() == mtype.FissionCampaignChannelTypeApp { return s.createApp(cpn, project) } return s.createWeb(cpn, project) } func (s *ChannelCreate) campaign() (cpn *model.FissionCampaign, project *model.Project, err error) { cpn, err = finder.Campaign(s.Ctx, s.Req.GetCampaignId(), s.Req.GetCampaignHashId()) if err != nil { err = s.BE().CacheError(err) return } if cpn == nil || cpn.IsDel == mtype.Yes { err = s.BE().VerifyError("not found campaign") return } project, err = finder.Project(s.Ctx, cpn.ProjectID) if err != nil { err = s.BE().CacheError(err) return } if project == nil || project.IsDel == mtype.Yes { err = s.BE().VerifyError("not found project") return } if s.Req.GetCType() == mtype.FissionCampaignChannelTypeWeb { if project.Scene == mtype.ProjectSceneWeb { // web项目不允许创建站外渠道 err = s.BE().VerifyError("web project not allow") return } if cpn.Target == mtype.FissionCampaignConfigTargetAdsGame { // 广告项目不允许创建站外 err = s.BE().VerifyError("ads campaign not allow") return } } return } func (s *ChannelCreate) _mark(cpnId int64) (mark string, err error) { m := s.GetDao().FissionCampaignChannel list, err := m.WithContext(s.Ctx).Where(m.CampaignID.Eq(cpnId)).Find() if err != nil { err = s.BE().MysqlError(err) return } var titleMap = make(map[string]struct{}) var markMap = make(map[string]struct{}, len(list)) for _, v := range list { markMap[strings.ToLower(v.Mark)] = struct{}{} if v.IsDel == mtype.No { titleMap[fmt.Sprintf("%s_%d", v.Title, v.CType)] = struct{}{} } } for i := 0; i < 100; i++ { mark = utils.GetRandEnStr(consts.ChannelMarkLen) if _, ok := markMap[strings.ToLower(mark)]; !ok { break } mark = "" } if mark == "" { err = workerr.BusyError return } if _, ok := titleMap[fmt.Sprintf("%s_%d", s.Req.GetTitle(), s.Req.GetCType())]; ok { err = workerr.CChanelExistError return } return } func (s *ChannelCreate) createApp(cpn *model.FissionCampaign, project *model.Project) (err error) { mark, err := s._mark(cpn.ID) if err != nil { return } m := s.GetDao().FissionCampaignChannel cl := withdefault.FissionCampaignChannel(&model.FissionCampaignChannel{ CampaignID: cpn.ID, Mark: mark, Title: s.Req.GetTitle(), CType: mtype.FissionCampaignChannelTypeApp, }) if err = m.WithContext(s.Ctx).Create(cl); err != nil { return s.BE().MysqlError(err) } var url string switch cpn.Target { case mtype.FissionCampaignConfigTargetAdsGame: url = blink.NewAdsLink(project.Domain, cpn.HashID, cl.Mark).CampaignShareLink() default: url = blink.NewCampaignLink(project.Domain, cpn.HashID, cl.Mark).CampaignShareLink() } s.Res.Id = cl.ID s.Res.Url = url return } func (s *ChannelCreate) createWeb(cpn *model.FissionCampaign, project *model.Project) (err error) { mark, err := s._mark(cpn.ID) if err != nil { return } code, err := s._linkCode(cpn, project, mark) if err != nil { return } shortLink, err := s._shortLink(cpn, project, mark) m := s.GetDao().FissionCampaignChannel cl := withdefault.FissionCampaignChannel(&model.FissionCampaignChannel{ CampaignID: cpn.ID, Mark: mark, Title: s.Req.GetTitle(), CType: mtype.FissionCampaignChannelTypeWeb, Code: code, ShortLink: shortLink, }) if err = m.WithContext(s.Ctx).Create(cl); err != nil { return s.BE().MysqlError(err) } s.Res.Id = cl.ID s.Res.Url = blink.NewCampaignLink(project.Domain, cpn.HashID, cl.Mark).CampaignWebLink() return } func (s *ChannelCreate) _shortLink(cpn *model.FissionCampaign, project *model.Project, mark string) (link string, err error) { res, err := app.NewShortLinkNameLink().CreateShortLink(s.Ctx, &linkpb.CreateShortLinkReq{ LongLink: blink.NewCampaignLink(project.Domain, cpn.HashID, mark).CampaignWebLink(), Domain: project.Domain, }) if err != nil { return } return res.GetShortLink(), nil } func (s *ChannelCreate) _linkCode(cpn *model.FissionCampaign, project *model.Project, mark string) (code string, err error) { m := s.GetDao().FissionCampaignChannel dfc, err := m.WithContext(s.Ctx).Where( m.CampaignID.Eq(cpn.ID), m.CType.Eq(mtype.FissionCampaignChannelTypeApp), m.IsDefault.Eq(mtype.Yes), ).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if dfc == nil { err = s.BE().VerifyError("not found default channel") return } lk, err := app.NewDeepLinkLink().GetCampaignLinkShortInfo(s.Ctx, &dlinkpb.GetCampaignLinkShortInfoReq{ ProjectId: project.ID, CampaignId: cpn.ID, }) if err != nil { return } codeInfo, err := app.NewDeepLinkLink().CreateCampaignLinkCode(s.Ctx, &dlinkpb.CreateCampaignLinkCodeReq{ ProjectId: project.ID, LinkId: lk.GetLinkId(), Channel: mark, RedirectUrl: blink.NewCampaignLink(project.Domain, cpn.HashID, dfc.Mark, blink.SetCwMark(mark)).CampaignCodeLink(), }) if err != nil { return } return codeInfo.GetCode(), nil } func (s *ChannelCreate) afterDone(cpn *model.FissionCampaign) { m := s.GetDao().FissionCampaign m.WithContext(s.Ctx).Where(m.ID.Eq(cpn.ID)).UpdateSimple(m.UpdatedAt.Value(time.Now().Unix())) _ = cache.NewCampaign(s.Ctx).Clear(cpn) }