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.
442 lines
10 KiB
Go
442 lines
10 KiB
Go
package campaignuser
|
|
|
|
import (
|
|
"joybuywork/internal/app"
|
|
"joybuywork/internal/consts"
|
|
"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/service/cmm"
|
|
"joybuywork/internal/service/provider"
|
|
"joybuywork/internal/service/provider/fissionaction"
|
|
"joybuywork/internal/service/provider/pusher"
|
|
"joybuywork/internal/utils"
|
|
"joybuywork/internal/utils/blink"
|
|
"joybuywork/internal/utils/lockdo"
|
|
"joybuywork/internal/utils/logic"
|
|
pb "joybuywork/proto/go_proto/w_campaign_user"
|
|
"joybuywork/proto/go_proto/workerr"
|
|
"strings"
|
|
"time"
|
|
|
|
c_fuserpb "gits.branchcn.com/backend/certified/proto/go_proto/c_fuser"
|
|
ddevicepb "gits.branchcn.com/backend/deeplink/proto/go_proto/ddevice"
|
|
linkpb "gits.branchcn.com/backend/shortlink/proto/go_proto/link"
|
|
)
|
|
|
|
type Visit struct {
|
|
logic.Logic
|
|
Req *pb.VisitReq
|
|
Res *pb.VisitRes
|
|
|
|
clearUser bool // 是否已经清楚的用户缓存
|
|
|
|
changeLangMark, changeLvMark bool //一些数据是否有被更改
|
|
|
|
cpnControl *provider.CampaignTZ
|
|
|
|
wbu *model.FissionWebUser
|
|
|
|
device *ddevicepb.FindBlackboxRes
|
|
}
|
|
|
|
func (s *Visit) Run() error {
|
|
return logic.Run(s)
|
|
}
|
|
|
|
func (s *Visit) Exec() (err error) {
|
|
cpn, channel, err := s.campaign()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
user, err := s.user(cpn, channel)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
err = s.setLink(cpn, channel, user)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
err = s.token(cpn, user)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return s.track(cpn, user)
|
|
}
|
|
|
|
func (s *Visit) campaign() (cpn *model.FissionCampaign, channel *model.FissionCampaignChannel, err error) {
|
|
|
|
cpn, err = finder.Campaign(s.Ctx, s.Req.GetHid())
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
if cpn == nil || cpn.IsDel == mtype.Yes {
|
|
err = workerr.NotFound("not found cpn")
|
|
return
|
|
}
|
|
|
|
err = s._cert(cpn.ProjectID)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 用户要绑定的渠道
|
|
channel, err = cmm.NewCMM(s.Ctx, s.GetDao()).UserBindChannel(cpn.ID, s.Req.GetCid())
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if s.Req.GetLang() == "" {
|
|
s.Req.Lang = cpn.GetLangMarks()[0]
|
|
}
|
|
|
|
if s.Req.GetWid() != "" {
|
|
s.wbu, err = cache.NewFissionWebUser(s.Ctx).FindByWebId(cpn.ID, s.Req.GetWid())
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
}
|
|
|
|
s.cpnControl = provider.NewCampaignTZ(s.Ctx, cpn, s.Req.Lang)
|
|
|
|
err = s._hasParent(cpn)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Visit) user(cpn *model.FissionCampaign, channel *model.FissionCampaignChannel) (user *model.FissionUser, err error) {
|
|
defer func() {
|
|
if err == nil && user != nil && user.IsView != mtype.Yes {
|
|
s.Res.HasParent = user.ParentID > 0
|
|
}
|
|
|
|
if err == nil && user != nil && s.wbu == nil {
|
|
s.wbu, err = cache.NewFissionWebUser(s.Ctx).FindByUserId(cpn.ID, user.ID)
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
|
|
pfu := provider.NewFissionUser(s.Ctx, cpn, channel)
|
|
user, err = pfu.VisitUser(
|
|
s.Req.GetUid(),
|
|
s.Req.GetPlatform(),
|
|
s.Req.GetLang(),
|
|
s.Req.GetLv(),
|
|
s.Req.GetCustomParam(),
|
|
s.Req.GetIp(),
|
|
s.Req.GetCenterId(),
|
|
s.Req.GetModuleId(),
|
|
s._getDevice(cpn.ProjectID),
|
|
s.wbu,
|
|
)
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
s.changeLangMark, s.changeLvMark = pfu.GetChangeLangMark(), pfu.GetChangeLvMark()
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Visit) token(cpn *model.FissionCampaign, user *model.FissionUser) (err error) {
|
|
res, err := app.NewCertifiedFUser().Token(s.Ctx, &c_fuserpb.TokenReq{
|
|
Id: user.ID,
|
|
CampaignId: user.CampaignID,
|
|
ChannelId: user.ChannelID,
|
|
Pid: user.ParentID,
|
|
IsView: user.IsView == mtype.Yes,
|
|
Lang: utils.NotExistGetFirst[string](user.LangMark, cpn.GetLangMarks()),
|
|
Lv: user.UserLevelMark,
|
|
ShowLang: user.LangMark,
|
|
Country: user.UserCountry,
|
|
Tz: consts.CampaignTz,
|
|
TzOffset: s.cpnControl.GetTz(),
|
|
})
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
s.Res.Id = user.ID
|
|
s.Res.HashId = user.HashID
|
|
s.Res.Token = res.GetToken()
|
|
s.Res.Expired = res.GetExpired()
|
|
s.Res.IsView = int32(user.IsView)
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Visit) setLink(cpn *model.FissionCampaign, channel *model.FissionCampaignChannel, user *model.FissionUser) (err error) {
|
|
if user.ShareLink != "" && !s.changeLvMark && !s.changeLangMark {
|
|
return
|
|
}
|
|
|
|
project, err := finder.Project(s.Ctx, cpn.ProjectID)
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
// 把分享链接变成短链
|
|
shareLink, err := s._shareLink(cpn, project, channel, user)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
res, _ := app.NewShortLinkNameLink().CreateShortLink(s.Ctx, &linkpb.CreateShortLinkReq{
|
|
LongLink: shareLink,
|
|
Domain: project.Domain,
|
|
})
|
|
|
|
if res.GetShortLink() == "" {
|
|
return
|
|
}
|
|
|
|
m := s.GetDao().FissionUser
|
|
_, _ = m.WithContext(s.Ctx).Where(m.ID.Eq(user.ID)).UpdateSimple(m.ShareLink.Value(res.GetShortLink()))
|
|
|
|
ms := s.GetDao().FissionUser.SubTable(cpn.ID)
|
|
_, _ = ms.WithContext(s.Ctx).Where(ms.ID.Eq(user.ID)).UpdateSimple(ms.ShareLink.Value(res.GetShortLink()))
|
|
|
|
s.AddAfterRun(func() (err error) {
|
|
if s.clearUser {
|
|
return
|
|
}
|
|
|
|
// 清除缓存
|
|
_ = cache.NewFissionUser(s.Ctx, cpn.ID).Clear(user)
|
|
s.clearUser = true
|
|
return
|
|
})
|
|
|
|
return
|
|
}
|
|
|
|
// 获取分享链接
|
|
func (s *Visit) _shareLink(cpn *model.FissionCampaign, project *model.Project, appChannel *model.FissionCampaignChannel, user *model.FissionUser) (link string, err error) {
|
|
conf, err := cache.NewCampaignConfig(s.Ctx).FindByCampaignId(cpn.ID)
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
if project.Scene == mtype.ProjectSceneWeb {
|
|
link = blink.NewCampaignLink(
|
|
project.Domain, cpn.HashID, appChannel.Mark,
|
|
blink.SetSubUserId(s.Req.GetUid()),
|
|
blink.SetScene(project.Scene),
|
|
blink.SetLang(user.LangMark),
|
|
blink.SetLevel(user.LevelMark),
|
|
).CampaignWebShareLink()
|
|
return
|
|
}
|
|
|
|
if conf.HasWeb == mtype.No {
|
|
link = blink.NewCampaignLink(
|
|
project.Domain, cpn.HashID, appChannel.Mark,
|
|
blink.SetSubUserId(s.Req.GetUid()),
|
|
blink.SetLang(user.LangMark),
|
|
blink.SetLevel(user.LevelMark),
|
|
).CampaignDownloadLink()
|
|
return
|
|
}
|
|
|
|
m := s.GetDao().FissionCampaignChannel
|
|
var webChannel *model.FissionCampaignChannel
|
|
if s.wbu == nil {
|
|
webChannel, err = m.WithContext(s.Ctx).Where(
|
|
m.CampaignID.Eq(cpn.ID),
|
|
m.IsDefault.Eq(mtype.Yes),
|
|
m.IsDel.Eq(mtype.No),
|
|
m.CType.Eq(mtype.FissionCampaignChannelTypeWeb),
|
|
).Take()
|
|
} else {
|
|
webChannel, err = m.WithContext(s.Ctx).Where(
|
|
m.ID.Eq(s.wbu.ChannelID),
|
|
).Take()
|
|
}
|
|
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
if webChannel == nil {
|
|
return
|
|
}
|
|
|
|
link = blink.NewCampaignLink(
|
|
project.Domain, cpn.HashID, webChannel.Mark,
|
|
blink.SetSubUserId(s.Req.GetUid()),
|
|
blink.SetLang(user.LangMark),
|
|
blink.SetLevel(user.LevelMark),
|
|
).CampaignWebLink()
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Visit) _cert(project int64) (err error) {
|
|
if s.Req.GetUid() == consts.FissionViewer {
|
|
return
|
|
}
|
|
// 数据验签
|
|
cert, err := app.NewCertifiedFUser().CertUser(s.Ctx, &c_fuserpb.CertUserReq{
|
|
ProjectId: project,
|
|
UserId: s.Req.GetUid(),
|
|
Lv: s.Req.GetLv(),
|
|
Lang: s.Req.GetLang(),
|
|
Time: s.Req.GetCert().GetTime(),
|
|
Blackbox: s.Req.GetCert().GetBlackbox(),
|
|
Version: s.Req.GetCert().GetVersion(),
|
|
Platform: s.Req.GetCert().GetPlatform(),
|
|
Token: s.Req.GetCert().GetToken(),
|
|
})
|
|
|
|
if err != nil || !cert.GetOk() {
|
|
err = workerr.UnauthorizedError
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Visit) _white(conf *model.FissionCampaignConfig, userId string) (err error) {
|
|
if userId == consts.FissionViewer {
|
|
return
|
|
}
|
|
|
|
if s.cpnControl.IsWait() && conf.HasWarmUp == mtype.No {
|
|
return workerr.CNotRunError
|
|
}
|
|
|
|
if s.cpnControl.IsPre() {
|
|
userIdList := strings.Split(conf.WhiteList, ";")
|
|
for _, id := range userIdList {
|
|
if userId == id {
|
|
return
|
|
}
|
|
}
|
|
return workerr.CNotRunError
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Visit) _getDevice(projectId int64) *ddevicepb.FindBlackboxRes {
|
|
if s.device == nil && s.Req.GetCert().GetBlackbox() != "" {
|
|
s.device, _ = app.NewDeepLinkDevice().FindBlackbox(s.Ctx, &ddevicepb.FindBlackboxReq{
|
|
Blackbox: s.Req.GetCert().GetBlackbox(),
|
|
ProjectId: projectId,
|
|
})
|
|
}
|
|
|
|
return s.device
|
|
}
|
|
|
|
// 是否有上级
|
|
func (s *Visit) _hasParent(cpn *model.FissionCampaign) (err error) {
|
|
|
|
device := s._getDevice(cpn.ProjectID)
|
|
if device == nil || device.GetDeviceId() == "" {
|
|
return
|
|
}
|
|
|
|
//看看能不能找到device的参与数据
|
|
cc := cache.NewFissionUser(s.Ctx, cpn.ID)
|
|
user, err := cc.FindByDeviceId(device.GetDeviceId())
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
if user != nil {
|
|
s.Res.HasParent = user.ParentID > 0
|
|
return
|
|
}
|
|
|
|
if device.GetLastParentUserId() == "" {
|
|
return
|
|
}
|
|
|
|
// 怀疑没入库,好这个上级用户是不是这个活动的,是就认为他有上级
|
|
user, err = cc.FindBySubUserId(device.GetLastParentUserId())
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
s.Res.HasParent = user != nil
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Visit) track(cpn *model.FissionCampaign, user *model.FissionUser) (err error) {
|
|
inApp := fissionaction.NewMarkPoint(s.Ctx).InApp(user)
|
|
|
|
if s.Req.GetCenterId() != "" {
|
|
inApp.CenterDrainage(time.Now().Unix(), s.Req.GetCenterId(), s.Req.GetModuleId())
|
|
}
|
|
|
|
inApp.View(time.Now().Unix(), s.Req.GetIp(), s.Req.GetOs(), s.Req.GetOsVersion(), s.Req.GetDeviceModel())
|
|
|
|
data, err := lockdo.Bytes(s.Ctx, ckey.FissionRewardPushOpenOnce(cpn.ID, mtype.FissionCampaignPushMarkVisit), func() (data []byte, err error) {
|
|
|
|
pushM := s.GetDao().FissionCampaignPush
|
|
push, err := pushM.WithContext(s.Ctx).Where(pushM.CampaignID.Eq(cpn.ID), pushM.Mark.Eq(mtype.FissionCampaignPushMarkVisit)).Take()
|
|
if err = dbcheck.DbError(err); err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
if push == nil {
|
|
push = &model.FissionCampaignPush{}
|
|
}
|
|
|
|
return jsonm.Marshal(push)
|
|
})
|
|
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
var push = &model.FissionCampaignPush{}
|
|
err = jsonm.Unmarshal(data, push)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if push.Open != mtype.Yes {
|
|
return
|
|
}
|
|
|
|
p, err := pusher.NewPusher(s.Ctx, cpn)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
err = p.Visit(user, time.Now())
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
}
|
|
|
|
return
|
|
}
|