|
|
package provider
|
|
|
|
|
|
import (
|
|
|
"context"
|
|
|
"joybuywork/internal/app"
|
|
|
"joybuywork/internal/consts"
|
|
|
"joybuywork/internal/consts/ckey"
|
|
|
"joybuywork/internal/repository/cache"
|
|
|
"joybuywork/internal/repository/finder"
|
|
|
"joybuywork/internal/repository/model"
|
|
|
"joybuywork/internal/repository/mtype"
|
|
|
"joybuywork/internal/repository/withdefault"
|
|
|
"joybuywork/internal/service/provider/s2s"
|
|
|
"joybuywork/internal/service/queue/producer"
|
|
|
"joybuywork/internal/service/queue/types"
|
|
|
"joybuywork/internal/utils"
|
|
|
"joybuywork/internal/utils/lockdo"
|
|
|
"joybuywork/internal/utils/logic"
|
|
|
"joybuywork/internal/utils/merr"
|
|
|
"joybuywork/internal/utils/verify"
|
|
|
"strings"
|
|
|
"time"
|
|
|
|
|
|
"joybuywork/proto/go_proto/workerr"
|
|
|
|
|
|
ddevicepb "gits.branchcn.com/backend/deeplink/proto/go_proto/ddevice"
|
|
|
"gits.branchcn.com/backend/microcode/plugins/derivative/lock"
|
|
|
"gorm.io/gen/field"
|
|
|
)
|
|
|
|
|
|
type FissionUser struct {
|
|
|
logic.Context
|
|
|
|
|
|
user *model.FissionUser
|
|
|
cpn *model.FissionCampaign
|
|
|
channel *model.FissionCampaignChannel
|
|
|
|
|
|
conf *model.FissionCampaignConfig
|
|
|
cpnControl *CampaignTZ
|
|
|
|
|
|
upData, msUpData []field.AssignExpr
|
|
|
|
|
|
changeLangMark bool
|
|
|
changeLvMark bool
|
|
|
|
|
|
subUserIdLock, deviceIdLock *lock.RedisLock
|
|
|
}
|
|
|
|
|
|
func NewFissionUser(ctx context.Context, cpn *model.FissionCampaign, channel *model.FissionCampaignChannel, opts ...logic.CtxOption) *FissionUser {
|
|
|
user := &FissionUser{
|
|
|
cpn: cpn,
|
|
|
channel: channel,
|
|
|
}
|
|
|
|
|
|
user.BaseInit(ctx, merr.NewBE(ctx), opts...)
|
|
|
|
|
|
return user
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) NotifyUser(behaviorTime, noticeType int64, isInstall bool, noticeTag, userMark, uid, deviceId, lvMark, lang, platform, customParam string, webChannelId, channelId int64, expTime time.Duration, parent *model.FissionUser) (user, bindParent *model.FissionUser, newUser bool, err error) {
|
|
|
defer s.lockRelease()
|
|
|
cpn := s.cpn
|
|
|
uct, err := s.userCampaignType(lang, lvMark, "")
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 如果没有关联的上级,尝试找一下
|
|
|
defer func() {
|
|
|
if err != nil || user == nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = s._refresh(user)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if (parent == nil || parent.ID != user.ParentID) && user.ParentID > 0 {
|
|
|
bindParent, err = finder.FissionUser(s.Ctx, cpn.ID, user.ParentID)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
} else {
|
|
|
bindParent = parent
|
|
|
}
|
|
|
|
|
|
if newUser {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
}()
|
|
|
|
|
|
user, err = s.notifyFindUser(noticeType, uct, userMark, uid, deviceId, platform, lang, lvMark, customParam, webChannelId)
|
|
|
if err != nil || user != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if uid != "" {
|
|
|
lc := s.getSubUserIdLock(uid)
|
|
|
if lc.Error() != nil {
|
|
|
err = workerr.BusyError
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if deviceId != "" {
|
|
|
lc := s.getDeviceIdLock(deviceId)
|
|
|
if lc.Error() != nil {
|
|
|
err = workerr.BusyError
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 再重新查一次
|
|
|
user, err = s.notifyFindUser(noticeType, uct, userMark, uid, deviceId, platform, lang, lvMark, customParam, webChannelId)
|
|
|
if err != nil || user != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if cpn.FissionID == consts.IdKeep && user == nil && noticeType == types.NoticeTypeCustom {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
lvMark, err = s._lvMark(uid, lang, lvMark, mtype.LVApiLogSourceNotifyUser)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
//新的活动用户
|
|
|
newUser = true
|
|
|
user = withdefault.FissionUser(&model.FissionUser{
|
|
|
CreatedAt: behaviorTime,
|
|
|
CampaignID: cpn.ID,
|
|
|
ChannelID: 0,
|
|
|
ParentID: 0,
|
|
|
Deep: 0,
|
|
|
IsNew: utils.Ternary[int8](isInstall, mtype.Yes, mtype.No),
|
|
|
SubUserID: uid,
|
|
|
DeviceID: deviceId,
|
|
|
UserMark: utils.Ternary[string](uid == "", deviceId, uid),
|
|
|
UserType: mtype.FissionUserTypePlay,
|
|
|
ParentIds: "",
|
|
|
IsView: utils.Ternary[int8](uid == consts.FissionViewer, mtype.Yes, mtype.No),
|
|
|
ShareLink: "",
|
|
|
Source: 0,
|
|
|
LangMark: lang,
|
|
|
UserLang: uct.LangMark,
|
|
|
LevelMark: lvMark,
|
|
|
UserLevelMark: uct.LevelMark,
|
|
|
UserLevel: uct.LevelId,
|
|
|
})
|
|
|
|
|
|
switch noticeType {
|
|
|
case types.NoticeTypeOpen:
|
|
|
user.Source = mtype.FissionUserSourceOpen
|
|
|
case types.NoticeTypeInstall:
|
|
|
user.Source = mtype.FissionUserSourceInstall
|
|
|
if noticeTag == types.NoticeTagWeb {
|
|
|
user.Source = mtype.FissionUserSourceWebFirstOpen
|
|
|
}
|
|
|
case types.NoticeTypeRegister:
|
|
|
user.Source = mtype.FissionUserSourceRegister
|
|
|
case types.NoticeTypeCustom:
|
|
|
user.Source = mtype.FissionUserSourceCustom
|
|
|
case types.NoticeTypePay:
|
|
|
user.Source = mtype.FissionUserSourcePay
|
|
|
}
|
|
|
|
|
|
if parent != nil {
|
|
|
user.ParentID = parent.ID
|
|
|
user.ChannelID = parent.ChannelID
|
|
|
user.Deep = parent.Deep + 1
|
|
|
user.LangMark = utils.STernary[string](lang, "", parent.LangMark)
|
|
|
|
|
|
if parent.ParentID > 0 {
|
|
|
user.SetParentIds(append(parent.GetParentIds(), parent.ParentID))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 如果没绑定上级的渠道,就绑定来源渠道
|
|
|
if channelId > 0 && user.ChannelID == 0 {
|
|
|
user.ChannelID = channelId
|
|
|
}
|
|
|
|
|
|
err = s._create(user, uct, platform, lvMark, customParam, "", "", webChannelId)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if user.SubUserID != "" {
|
|
|
producer.NewCampaignNotice(s.Ctx).ProjectUser(types.ProjectUser{
|
|
|
ProjectId: cpn.ProjectID,
|
|
|
UserId: user.SubUserID,
|
|
|
})
|
|
|
}
|
|
|
|
|
|
app.Redis.Cache.Set(s.Ctx, ckey.FissionUserUniqMark(cpn.ID, userMark), user.ID, expTime)
|
|
|
app.Redis.Cache.Set(s.Ctx, ckey.FissionUserIovdMark(user.ID), userMark, expTime)
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) VisitUser(uid, platform, lang, lvMark, customParam, ip, centerHashId, moduleId string, device *ddevicepb.FindBlackboxRes, wbu *model.FissionWebUser) (user *model.FissionUser, err error) {
|
|
|
defer s.lockRelease()
|
|
|
|
|
|
defer func() {
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
err = s._refresh(user)
|
|
|
}()
|
|
|
|
|
|
lvMark, err = s._lvMark(uid, lang, lvMark, mtype.LVApiLogSourceVisitUser)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
conf, err := s.getConf()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var webChancelId int64
|
|
|
if wbu != nil {
|
|
|
webChancelId = wbu.ChannelID
|
|
|
}
|
|
|
|
|
|
userId := utils.Ternary[string](uid == "", consts.FissionViewer, uid)
|
|
|
|
|
|
// 白名单校验
|
|
|
err = s._white(conf, userId, lang)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
countryMark := s._country(conf.RewardGroup, ip)
|
|
|
|
|
|
user, err = s._findBySubUserId(userId)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
uct, err := s.userCampaignType(lang, lvMark, countryMark)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
//有用户,或者活动结束了
|
|
|
if user != nil {
|
|
|
user = s._refreshAttr(user, uct, platform, lang, lvMark, customParam, centerHashId, moduleId, webChancelId)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var deviceId string
|
|
|
var parent *model.FissionUser
|
|
|
if userId != consts.FissionViewer {
|
|
|
user, parent, deviceId, err = s._deviceUser(device, uid, conf)
|
|
|
if err != nil || user != nil {
|
|
|
user = s._refreshSubUserId(user, uid)
|
|
|
user = s._refreshAttr(user, uct, platform, lang, lvMark, customParam, centerHashId, moduleId, webChancelId)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//加锁来创建
|
|
|
lc := s.getSubUserIdLock(userId).Lock()
|
|
|
if lc.Error() != nil {
|
|
|
err = workerr.BusyError
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if deviceId != "" {
|
|
|
lc1 := s.getDeviceIdLock(deviceId).Lock()
|
|
|
if lc1.Error() != nil {
|
|
|
err = workerr.BusyError
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//获取到锁再找一次
|
|
|
user, err = s._findBySubUserId(userId)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if user != nil {
|
|
|
user = s._refreshAttr(user, uct, platform, lang, lvMark, customParam, centerHashId, moduleId, webChancelId)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
//创建用户
|
|
|
user = withdefault.FissionUser(&model.FissionUser{
|
|
|
CampaignID: s.cpn.ID,
|
|
|
SubUserID: userId,
|
|
|
DeviceID: deviceId,
|
|
|
UserMark: utils.Ternary[string](userId != "", userId, deviceId),
|
|
|
UserType: utils.Ternary[int8](s.cpn.EndTime < time.Now().Unix(), mtype.FissionUserTypeVisitor, mtype.FissionUserTypePlay),
|
|
|
IsView: utils.Ternary[int8](userId == consts.FissionViewer, mtype.Yes, mtype.No),
|
|
|
Source: mtype.FissionUserSourceVisit,
|
|
|
LangMark: lang,
|
|
|
LevelMark: lvMark,
|
|
|
UserLevelMark: uct.LevelMark,
|
|
|
UserLevel: uct.LevelId,
|
|
|
UserLang: uct.LangMark,
|
|
|
UserCountry: uct.CountryMark,
|
|
|
})
|
|
|
|
|
|
if s.channel != nil {
|
|
|
user.ChannelID = s.channel.ID
|
|
|
}
|
|
|
|
|
|
if parent != nil {
|
|
|
user.ParentID = parent.ID
|
|
|
user.ChannelID = parent.ChannelID
|
|
|
user.Deep = parent.Deep + 1
|
|
|
|
|
|
if parent.ParentID > 0 {
|
|
|
user.SetParentIds(append(parent.GetParentIds(), parent.ParentID))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
err = s._create(user, uct, platform, lvMark, customParam, centerHashId, moduleId, webChancelId)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if user.SubUserID != "" {
|
|
|
producer.NewCampaignNotice(s.Ctx).ProjectUser(types.ProjectUser{
|
|
|
ProjectId: s.cpn.ProjectID,
|
|
|
UserId: user.SubUserID,
|
|
|
})
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) GetChangeLangMark() bool {
|
|
|
return s.changeLangMark
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) GetChangeLvMark() bool {
|
|
|
return s.changeLvMark
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) getSubUserIdLock(userId string) *lock.RedisLock {
|
|
|
if s.subUserIdLock == nil {
|
|
|
s.subUserIdLock = app.NewRedisLock(s.Ctx, ckey.FissionUserStoreOnce(s.cpn.ID, userId))
|
|
|
}
|
|
|
|
|
|
return s.subUserIdLock
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) getDeviceIdLock(deviceId string) *lock.RedisLock {
|
|
|
if s.deviceIdLock == nil {
|
|
|
s.deviceIdLock = app.NewRedisLock(s.Ctx, ckey.FissionUserStoreDeviceOnce(s.cpn.ID, deviceId))
|
|
|
}
|
|
|
|
|
|
return s.deviceIdLock
|
|
|
}
|
|
|
func (s *FissionUser) lockRelease() {
|
|
|
if s.subUserIdLock != nil {
|
|
|
s.subUserIdLock.Release()
|
|
|
}
|
|
|
|
|
|
if s.deviceIdLock != nil {
|
|
|
s.deviceIdLock.Release()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) getConf() (conf *model.FissionCampaignConfig, err error) {
|
|
|
if s.conf == nil {
|
|
|
s.conf, err = cache.NewCampaignConfig(s.Ctx).FindByCampaignId(s.cpn.ID)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return s.conf, nil
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) getTz(lang string) *CampaignTZ {
|
|
|
if s.cpnControl == nil {
|
|
|
s.cpnControl = NewCampaignTZ(s.Ctx, s.cpn, lang)
|
|
|
}
|
|
|
|
|
|
return s.cpnControl
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) _white(conf *model.FissionCampaignConfig, userId, lang string) (err error) {
|
|
|
if userId == consts.FissionViewer {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
tz := s.getTz(lang)
|
|
|
if tz.IsWait() && conf.HasWarmUp == mtype.No {
|
|
|
return workerr.CNotRunError
|
|
|
}
|
|
|
|
|
|
if tz.IsPre() {
|
|
|
userIdList := strings.Split(conf.WhiteList, ";")
|
|
|
for _, id := range userIdList {
|
|
|
if userId == id {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
return workerr.CNotRunError
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) _refresh(user *model.FissionUser) (err error) {
|
|
|
if len(s.upData) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionUser
|
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(user.ID)).UpdateSimple(s.upData...)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
ms := s.GetDao().FissionUser.SubTable(s.cpn.ID)
|
|
|
_, err = ms.WithContext(s.Ctx).Where(ms.ID.Eq(user.ID)).UpdateSimple(s.msUpData...)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 清除缓存
|
|
|
_ = cache.NewFissionUser(s.Ctx, user.CampaignID).Clear(user)
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) _country(rewardGroup int8, ip string) string {
|
|
|
var countryMark string
|
|
|
if rewardGroup == mtype.FissionRewardGroupCountry && ip != "" {
|
|
|
res, _ := app.NewDeepLinkDevice().FindIpAreaCode(s.Ctx, &ddevicepb.FindIpAreaCodeReq{Ip: ip})
|
|
|
countryMark = res.GetAreaCode()
|
|
|
}
|
|
|
|
|
|
return countryMark
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) _findBySubUserId(userId string) (user *model.FissionUser, err error) {
|
|
|
if userId == "" {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
user, err = cache.NewFissionUser(s.Ctx, s.cpn.ID).FindBySubUserId(userId)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) _findByDeviceId(deviceId string) (user *model.FissionUser, err error) {
|
|
|
if deviceId == "" {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
user, err = cache.NewFissionUser(s.Ctx, s.cpn.ID).FindByDeviceId(deviceId)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) _refreshDeviceId(user *model.FissionUser, deviceId string) *model.FissionUser {
|
|
|
m := s.GetDao().FissionUser
|
|
|
ms := s.GetDao().FissionUser.SubTable(s.cpn.ID)
|
|
|
|
|
|
if user.DeviceID == "" && deviceId != "" {
|
|
|
s.upData = append(s.upData, m.DeviceID.Value(deviceId))
|
|
|
s.msUpData = append(s.msUpData, ms.DeviceID.Value(deviceId))
|
|
|
user.DeviceID = deviceId
|
|
|
|
|
|
if user.SubUserID == "" && user.UserMark == "" {
|
|
|
s.upData = append(s.upData, m.UserMark.Value(deviceId))
|
|
|
s.msUpData = append(s.msUpData, ms.UserMark.Value(deviceId))
|
|
|
user.UserMark = deviceId
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return user
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) _refreshSubUserId(user *model.FissionUser, subUserId string) *model.FissionUser {
|
|
|
m := s.GetDao().FissionUser
|
|
|
ms := s.GetDao().FissionUser.SubTable(s.cpn.ID)
|
|
|
|
|
|
if user.SubUserID == "" && subUserId != "" {
|
|
|
s.upData = append(s.upData, m.SubUserID.Value(subUserId), m.UserMark.Value(subUserId))
|
|
|
s.msUpData = append(s.msUpData, ms.SubUserID.Value(subUserId), m.UserMark.Value(subUserId))
|
|
|
user.SubUserID = subUserId
|
|
|
user.UserMark = subUserId
|
|
|
|
|
|
if user.SubUserID != "" {
|
|
|
producer.NewCampaignNotice(s.Ctx).ProjectUser(types.ProjectUser{
|
|
|
ProjectId: s.cpn.ProjectID,
|
|
|
UserId: user.SubUserID,
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return user
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) _refreshAttr(user *model.FissionUser, uct consts.CampaignUserType, platform, lang, lvMark, customParam, centerHashId, moduleId string, webChannelId int64) *model.FissionUser {
|
|
|
attr := NewFissionUserAttr(s.Ctx, user)
|
|
|
|
|
|
m := s.GetDao().FissionUser
|
|
|
ms := s.GetDao().FissionUser.SubTable(s.cpn.ID)
|
|
|
channel := s.channel
|
|
|
|
|
|
// 如果用户没有绑定渠道,就绑定一下
|
|
|
if s.channel != nil && user.ChannelID == 0 {
|
|
|
s.upData = append(s.upData, m.ChannelID.Value(channel.ID))
|
|
|
s.msUpData = append(s.msUpData, ms.ChannelID.Value(channel.ID))
|
|
|
user.ChannelID = channel.ID
|
|
|
}
|
|
|
|
|
|
// 更换匹配中的语种
|
|
|
if user.UserLang != uct.LangMark {
|
|
|
s.upData = append(s.upData, m.UserLang.Value(uct.LangMark))
|
|
|
s.msUpData = append(s.msUpData, ms.UserLang.Value(uct.LangMark))
|
|
|
user.UserLang = uct.LangMark
|
|
|
}
|
|
|
|
|
|
// 更换匹配中的用户等级
|
|
|
if user.UserLevel != uct.LevelId && user.FixedUserLevel == mtype.No {
|
|
|
s.upData = append(s.upData, m.UserLevelMark.Value(uct.LevelMark), m.UserLevel.Value(uct.LevelId))
|
|
|
s.msUpData = append(s.msUpData, ms.UserLevelMark.Value(uct.LevelMark), ms.UserLevel.Value(uct.LevelId))
|
|
|
user.UserLevelMark = uct.LevelMark
|
|
|
user.UserLevel = uct.LevelId
|
|
|
}
|
|
|
|
|
|
// 更换匹配中的国家
|
|
|
if user.UserCountry != uct.CountryMark {
|
|
|
s.upData = append(s.upData, m.UserCountry.Value(uct.CountryMark))
|
|
|
s.msUpData = append(s.msUpData, ms.UserCountry.Value(uct.CountryMark))
|
|
|
user.UserCountry = uct.CountryMark
|
|
|
}
|
|
|
|
|
|
// 用户带的语言标识
|
|
|
if lang != "" && user.LangMark != lang {
|
|
|
s.upData = append(s.upData, m.LangMark.Value(lang))
|
|
|
s.msUpData = append(s.msUpData, ms.LangMark.Value(lang))
|
|
|
user.LangMark = lang
|
|
|
s.changeLangMark = true
|
|
|
|
|
|
_ = attr.Lang(lang)
|
|
|
}
|
|
|
|
|
|
if lvMark != "" {
|
|
|
// 用户带的用户等级标识
|
|
|
oldLv := strings.Split(user.LevelMark, ",")
|
|
|
setLv := strings.Split(lvMark, ",")
|
|
|
|
|
|
// 如果数组相等,并且也没有切换语种,那就更新了
|
|
|
if !verify.SliceEq(oldLv, setLv) {
|
|
|
s.upData = append(s.upData, m.LevelMark.Value(lvMark))
|
|
|
s.msUpData = append(s.msUpData, ms.LevelMark.Value(lvMark))
|
|
|
user.LevelMark = lvMark
|
|
|
|
|
|
_ = attr.UserLv(uct.LevelMark, setLv)
|
|
|
s.changeLvMark = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
_ = attr.Platform(platform)
|
|
|
|
|
|
_ = attr.Center(centerHashId)
|
|
|
_ = attr.CenterModule(moduleId)
|
|
|
|
|
|
_ = attr.CustomParam(customParam)
|
|
|
|
|
|
if webChannelId > 0 {
|
|
|
_ = attr.WebChannel(webChannelId)
|
|
|
}
|
|
|
|
|
|
return user
|
|
|
}
|
|
|
|
|
|
// 去拿deviceCode信息
|
|
|
func (s *FissionUser) _deviceUser(device *ddevicepb.FindBlackboxRes, uid string, conf *model.FissionCampaignConfig) (user, parent *model.FissionUser, deviceId string, err error) {
|
|
|
if device.GetDeviceId() == "" {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
//看看能不能找到device的参与数据
|
|
|
user, err = s._findByDeviceId(device.GetDeviceId())
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if user == nil {
|
|
|
deviceId = device.GetDeviceId()
|
|
|
|
|
|
if device.GetLastParentUserId() != "" {
|
|
|
parent, err = s._findBySubUserId(device.GetLastParentUserId())
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 这个deviceId被其他人绑定过的
|
|
|
if user.SubUserID == "" {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if conf.DeviceOnce == mtype.Yes && user.SubUserID != uid {
|
|
|
err = workerr.DeviceOnceError
|
|
|
return
|
|
|
}
|
|
|
|
|
|
user = nil
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) _findByUserMark(noticeType int64, userMark string) (user *model.FissionUser, err error) {
|
|
|
if !verify.InArray[int64](noticeType, types.NoticeTypeInstall, types.NoticeTypeOpen) || userMark == "" {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
id, _ := app.Redis.Cache.Get(s.Ctx, ckey.FissionUserUniqMark(s.cpn.ID, userMark)).Int64()
|
|
|
if id == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
user, err = cache.NewFissionUser(s.Ctx, s.cpn.ID).FindById(id)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) notifyFindUser(noticeType int64, uct consts.CampaignUserType, userMark, uid, deviceId, platform, lang, lvMark, customParam string, webChannelId int64) (user *model.FissionUser, err error) {
|
|
|
defer func() {
|
|
|
if user != nil {
|
|
|
user = s._refreshAttr(user, uct, platform, lang, lvMark, customParam, "", "", webChannelId)
|
|
|
}
|
|
|
}()
|
|
|
|
|
|
user, err = s._findByUserMark(noticeType, userMark)
|
|
|
if err != nil || user != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
user, err = s._findBySubUserId(uid)
|
|
|
if err != nil || user != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if user != nil {
|
|
|
user = s._refreshDeviceId(user, deviceId)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
user, err = s._findByDeviceId(deviceId)
|
|
|
if err != nil || user == nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 相同设备,但是不同用户id, 当新用户处理
|
|
|
if uid != "" && user.SubUserID != "" && user.SubUserID != uid {
|
|
|
user = nil
|
|
|
return
|
|
|
}
|
|
|
|
|
|
user = s._refreshSubUserId(user, uid)
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) _create(user *model.FissionUser, uct consts.CampaignUserType, platform, lvMark, customParam, centerHashId, moduleId string, webChannelId int64) (err error) {
|
|
|
ms := s.GetDao().FissionUser.SubTable(user.CampaignID)
|
|
|
if err = ms.WithContext(s.Ctx).Create(user); err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionUser
|
|
|
if err = m.WithContext(s.Ctx).Create(user); err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = s.GetDao().FissionUserStat.WithContext(s.Ctx).Create(withdefault.FissionUserStat(&model.FissionUserStat{
|
|
|
UserID: user.ID,
|
|
|
CampaignID: user.CampaignID,
|
|
|
}))
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
attr := NewFissionUserAttr(s.Ctx, user)
|
|
|
|
|
|
err = attr.WithUser(
|
|
|
platform,
|
|
|
user.LangMark,
|
|
|
uct.LevelMark, lvMark,
|
|
|
uct.CountryMark,
|
|
|
centerHashId,
|
|
|
moduleId,
|
|
|
webChannelId,
|
|
|
)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = attr.CustomParam(customParam)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// UserCampaignType 获取活动对应的用户所属类型数据
|
|
|
func (s *FissionUser) userCampaignType(langMark, lvMark, countryMark string) (uct consts.CampaignUserType, err error) {
|
|
|
cpn := s.cpn
|
|
|
conf, err := s.getConf()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var userLang, userLevelMark, userCountry string
|
|
|
var userLevel int64
|
|
|
defer func() {
|
|
|
|
|
|
if userLevel > 0 && userLevelMark == "" {
|
|
|
level, _ := cache.NewFissionUserLevel(s.Ctx).FindById(userLevel)
|
|
|
userLevelMark = level.Mark
|
|
|
}
|
|
|
|
|
|
uct.LangMark, uct.LevelId, uct.LevelMark, uct.CountryMark = userLang, userLevel, userLevelMark, userCountry
|
|
|
}()
|
|
|
|
|
|
ful := finder.NewFuserLayer(conf)
|
|
|
|
|
|
switch conf.RewardGroup {
|
|
|
case mtype.FissionRewardGroupUserLevel:
|
|
|
var dfId int64
|
|
|
lvMarks := strings.Split(lvMark, ",")
|
|
|
for _, mark := range lvMarks {
|
|
|
var lvId int64
|
|
|
lvId, err = cache.NewFissionUserLevel(s.Ctx).FindByMarkId(cpn.ProjectID, mark)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if lvId == 0 {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
if dfId == 0 {
|
|
|
dfId = lvId
|
|
|
}
|
|
|
|
|
|
_, df := ful.Level().Selected(lvId)
|
|
|
if !df {
|
|
|
userLevel = lvId
|
|
|
userLevelMark = mark
|
|
|
break
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if userLevel == 0 {
|
|
|
userLevel, _ = ful.Level().Selected(0)
|
|
|
}
|
|
|
|
|
|
case mtype.FissionRewardGroupLang:
|
|
|
userLang, _ = ful.Lang().Selected(langMark)
|
|
|
case mtype.FissionRewardGroupLangAndUserLevel:
|
|
|
|
|
|
userLang, _ = ful.LangLevel().GetLang(langMark)
|
|
|
|
|
|
var dfId int64
|
|
|
lvMarks := strings.Split(lvMark, ",")
|
|
|
for _, mark := range lvMarks {
|
|
|
var lvId int64
|
|
|
lvId, err = cache.NewFissionUserLevel(s.Ctx).FindByMarkId(cpn.ProjectID, mark)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if lvId == 0 {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
if dfId == 0 {
|
|
|
dfId = lvId
|
|
|
}
|
|
|
|
|
|
_, df := ful.LangLevel().GetLevel(userLang, lvId)
|
|
|
if !df {
|
|
|
userLevel = lvId
|
|
|
userLevelMark = mark
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if userLevel == 0 {
|
|
|
userLevel, _ = ful.LangLevel().GetLevel(userLang, 0)
|
|
|
}
|
|
|
|
|
|
case mtype.FissionRewardGroupCountry:
|
|
|
userCountry, _ = ful.Country().Selected(countryMark)
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *FissionUser) _lvMark(subUserId, langMark, lvMark, source string) (lv string, err error) {
|
|
|
if subUserId == "" {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
project, err := cache.NewProject(s.Ctx).FindById(s.cpn.ProjectID)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
conf, err := NewFissionConfig(s.Ctx, project)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
url, err := conf.GetLvUrl()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if url == nil {
|
|
|
return lvMark, nil
|
|
|
}
|
|
|
|
|
|
key := ckey.FissionLvApiCache(project.ID, subUserId)
|
|
|
err = lockdo.ExistDo(s.Ctx, key, func(exist bool) (err error) {
|
|
|
|
|
|
if exist {
|
|
|
lv = app.Redis.Cache.Get(s.Ctx, key).Val()
|
|
|
return
|
|
|
}
|
|
|
|
|
|
sts, err := s2s.NewLvApi(s.Ctx, conf.Config())
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
data, err := sts.LvApi(s.cpn, subUserId, langMark, source)
|
|
|
if err != nil {
|
|
|
err = nil
|
|
|
app.Redis.Cache.Set(s.Ctx, key, lv, 5*time.Second)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
lv = strings.Join(data.List, ",")
|
|
|
|
|
|
app.Redis.Cache.Set(s.Ctx, key, lv, 30*time.Second)
|
|
|
return
|
|
|
})
|
|
|
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|