You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
6.1 KiB
Go

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)
}