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.

260 lines
5.8 KiB
Go

package campaignuser
import (
"joybuywork/internal/app"
"joybuywork/internal/consts/ckey"
"joybuywork/internal/plugins/jsonm"
"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/service/cmm"
"joybuywork/internal/service/queue/producer"
"joybuywork/internal/service/queue/types"
"joybuywork/internal/utils/blink"
"joybuywork/internal/utils/logic"
pb "joybuywork/proto/go_proto/w_campaign_user"
"joybuywork/proto/go_proto/workerr"
linkpb "gits.branchcn.com/backend/shortlink/proto/go_proto/link"
)
type DynamicLink struct {
logic.Logic
Req *pb.DynamicLinkReq
Res *pb.DynamicLinkRes
}
func (s *DynamicLink) Run() error {
return logic.Run(s)
}
func (s *DynamicLink) Exec() (err error) {
project, cpn, channel, err := s.related()
if err != nil {
return
}
user, err := s.user(cpn, channel)
if err != nil {
return
}
err = s.link(cpn, user, project, channel)
if err != nil {
return
}
return
}
func (s *DynamicLink) related() (project *model.Project, cpn *model.FissionCampaign, channel *model.FissionCampaignChannel, err error) {
project, err = finder.Project(s.Ctx, s.Req.GetProjectHashId())
if err != nil {
err = s.BE().CacheError(err)
return
}
if project == nil || project.IsDel == mtype.Yes {
err = workerr.DynamicNotRelatedError
return
}
if s.Req.GetCampaignHashId() != "" {
cpn, err = finder.Campaign(s.Ctx, s.Req.GetCampaignHashId())
if err != nil {
err = s.BE().CacheError(err)
return
}
} else {
var conf *model.FissionConfig
conf, err = cmm.NewCMM(s.Ctx, s.GetDao()).GetFissionConfig(project.ID)
if err != nil {
return
}
cpn, err = finder.Campaign(s.Ctx, conf.DynamicCampaign)
if err != nil {
err = s.BE().CacheError(err)
return
}
}
if cpn == nil || cpn.IsDel == mtype.Yes {
err = workerr.DynamicNotRelatedError
return
}
channelM := s.GetDao().FissionCampaignChannel
channel, err = channelM.WithContext(s.Ctx).Where(
channelM.CampaignID.Eq(cpn.ID),
channelM.CType.Eq(mtype.FissionCampaignChannelTypeApp),
channelM.IsDefault.Eq(mtype.Yes),
channelM.IsDel.Eq(mtype.No),
).Take()
return
}
func (s *DynamicLink) user(cpn *model.FissionCampaign, channel *model.FissionCampaignChannel) (user *model.FissionUser, err error) {
if s.Req.GetSubUserId() == "" {
err = s.BE().VerifyError("sub_user_id empty")
return
}
user, err = cache.NewFissionUser(s.Ctx, cpn.ID).FindBySubUserId(s.Req.GetSubUserId())
if err != nil {
err = s.BE().CacheError(err)
return
}
if user != nil {
return
}
lc := app.NewRedisLock(s.Ctx, ckey.FissionUserStoreOnce(cpn.ID, s.Req.GetSubUserId())).Lock()
defer lc.Release()
if lc.Error() != nil {
err = workerr.BusyError
return
}
user, err = cache.NewFissionUser(s.Ctx, cpn.ID).FindBySubUserId(s.Req.GetSubUserId())
if err != nil {
err = s.BE().CacheError(err)
return
}
if user != nil {
return
}
user = withdefault.FissionUser(&model.FissionUser{
CampaignID: cpn.ID,
ChannelID: channel.ID,
ParentID: 0,
Deep: 0,
IsNew: 0,
SubUserID: s.Req.GetSubUserId(),
DeviceID: "",
UserMark: s.Req.GetSubUserId(),
UserType: mtype.FissionUserTypePlay,
ParentIds: "",
IsView: 0,
ShareLink: "",
Source: mtype.FissionUserSourceDynamic,
IsHelp: 0,
})
m := s.GetDao().FissionUser
if err = m.WithContext(s.Ctx).Create(user); err != nil {
err = s.BE().MysqlError(err)
return
}
ms := s.GetDao().FissionUser.SubTable(cpn.ID)
if err = ms.WithContext(s.Ctx).Create(user); err != nil {
err = s.BE().MysqlError(err)
return
}
producer.NewCampaignNotice(s.Ctx).ProjectUser(types.ProjectUser{
ProjectId: cpn.ProjectID,
UserId: user.SubUserID,
})
return
}
func (s *DynamicLink) link(cpn *model.FissionCampaign, user *model.FissionUser, project *model.Project, channel *model.FissionCampaignChannel) (err error) {
params := &mtype.FissionUserDyLinkParams{
MediaType: s.Req.GetMediaType(),
ImageText: nil,
}
switch s.Req.GetMediaType() {
case mtype.FissionUserDyLinkMediaTypeImgText:
for _, v := range s.Req.GetImageText() {
params.ImageText = append(params.ImageText, &mtype.ImageText{
NickName: v.GetNickName(),
Avatar: v.GetAvatar(),
Title: v.GetTitle(),
Desc: v.GetDesc(),
Image: v.GetImage(),
})
}
}
b, err := jsonm.Marshal(params)
if err != nil {
err = workerr.ServerError
return
}
mark, _ := b.ToMd5()
m := s.GetDao().FissionUserDylink
lk, err := m.WithContext(s.Ctx).Where(m.UserID.Eq(user.ID), m.LinkMark.Eq(mark)).Take()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
defer func() {
if err != nil {
return
}
s.Res.LinkUrl = lk.LinkURL
}()
if lk != nil {
return
}
lc := app.NewRedisLock(s.Ctx, ckey.FissionUserDyLinkOnce(user.ID, mark)).Lock()
defer lc.Release()
if err != nil {
err = workerr.BusyError
return
}
lk, err = m.WithContext(s.Ctx).Where(m.UserID.Eq(user.ID), m.LinkMark.Eq(mark)).Take()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
if lk != nil {
return
}
lk = withdefault.FissionUserDylink(&model.FissionUserDylink{
CampaignID: cpn.ID,
UserID: user.ID,
LinkMark: mark,
Params: b.ToString(),
})
link := blink.NewCampaignLink(project.Domain, cpn.HashID, channel.Mark, blink.SetSubUserId(user.SubUserID), blink.SetDyLinkId(lk.HashID)).CampaignDynamicLink()
res, err := app.NewShortLinkNameLink().CreateShortLink(s.Ctx, &linkpb.CreateShortLinkReq{
LongLink: link,
Domain: project.Domain,
})
if err != nil {
return
}
lk.LinkURL = res.GetShortLink()
if err = m.WithContext(s.Ctx).Create(lk); err != nil {
err = s.BE().MysqlError(err)
return
}
return
}