package games import ( "joybuywork/internal/app" "joybuywork/internal/consts" "joybuywork/internal/consts/ckey" "joybuywork/internal/plugins/hashid" "joybuywork/internal/plugins/jsonm" "joybuywork/internal/repository/cache" "joybuywork/internal/repository/dbcheck" "joybuywork/internal/repository/model" "joybuywork/internal/repository/mtype" "joybuywork/internal/repository/withdefault" "joybuywork/internal/service/queue/producer" "joybuywork/internal/service/queue/types" "joybuywork/internal/utils" "joybuywork/internal/utils/logic" pb "joybuywork/proto/go_proto/w_games" "joybuywork/proto/go_proto/workerr" "fmt" "math/rand" "time" c_fuserpb "gits.branchcn.com/backend/certified/proto/go_proto/c_fuser" c_guserpb "gits.branchcn.com/backend/certified/proto/go_proto/c_guser" ) type Visit struct { logic.Logic Req *pb.VisitReq Res *pb.VisitRes } func (s *Visit) Run() error { return logic.Run(s) } func (s *Visit) Data() (data jsonm.JsonM) { data, _ = jsonm.Marshal(s.Req) return } func (s *Visit) Exec() (err error) { project, err := s.project() if err != nil { return } link, err := s.link() if err != nil { return } user, err := s.user(project, link) if err != nil { return } err = s.token(user, link.ID) if err != nil { return } s.trace(user, link) return } func (s *Visit) project() (project *model.Project, err error) { project, err = cache.NewProject(s.Ctx).FindByHashId(s.Req.GetProjectHashId()) if err != nil { return } if project == nil { err = s.BE().VerifyError("not found project") return } return } func (s *Visit) link() (link *model.GameLink, err error) { m := s.GetDao().GameLink link, err = m.WithContext(s.Ctx).Where(m.HashID.Eq(s.Req.GetLinkHashId())).First() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if link == nil { err = s.BE().VerifyError("not found link") return } return } func (s *Visit) user(project *model.Project, link *model.GameLink) (user *model.GameUser, err error) { err = s._cert(project.ID) if err != nil { return } if s._isView() { return &model.GameUser{ ID: rand.Int63(), HashID: hashid.Id()[3:], ProjectID: project.ID, GameID: link.GameID, }, nil } if s.Req.GetUid() != "" { user, err = s._uid(project, link) if err != nil || user != nil { return } } user, err = s._iovd(project, link) if err != nil { return } return } func (s *Visit) _uid(project *model.Project, link *model.GameLink) (user *model.GameUser, err error) { m := s.GetDao().GameUser user, err = m.WithContext(s.Ctx).Where(m.ProjectID.Eq(project.ID), m.GameID.Eq(link.GameID), m.SubUserID.Eq(s.Req.GetUid())).Take() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if user != nil { return } user, err = s._iovd(project, link) if err != nil { return } if user != nil && user.SubUserID == "" { _, err = m.WithContext(s.Ctx).Where(m.ID.Eq(user.ID)).UpdateSimple(m.SubUserID.Value(s.Req.GetUid())) if err != nil { err = s.BE().MysqlError(err) return } return } user = withdefault.GameUser(&model.GameUser{ ProjectID: project.ID, GameID: link.GameID, IP: s.Req.GetIp(), Os: s.Req.GetOs(), Ver: s.Req.GetOsVersion(), DModel: s.Req.GetDeviceModel(), SubUserID: s.Req.GetUid(), IovdMark: s._iovdMark(), }) err = s.GetDao().GameUser.WithContext(s.Ctx).Create(user) if err != nil { err = s.BE().MysqlError(err) return } return } func (s *Visit) _iovd(project *model.Project, link *model.GameLink) (user *model.GameUser, err error) { m := s.GetDao().GameUser user, err = m.WithContext(s.Ctx).Where(m.ProjectID.Eq(project.ID), m.GameID.Eq(link.GameID), m.IovdMark.Eq(s._iovdMark())).Last() if err = dbcheck.DbError(err); err != nil { err = s.BE().MysqlError(err) return } if user != nil { return } user = withdefault.GameUser(&model.GameUser{ ProjectID: project.ID, GameID: link.GameID, IP: s.Req.GetIp(), Os: s.Req.GetOs(), Ver: s.Req.GetOsVersion(), DModel: s.Req.GetDeviceModel(), IovdMark: s._iovdMark(), }) err = s.GetDao().GameUser.WithContext(s.Ctx).Create(user) if err != nil { err = s.BE().MysqlError(err) return } return } func (s *Visit) token(user *model.GameUser, linkId int64) (err error) { res, err := app.NewCertifiedGUser().Token(s.Ctx, &c_guserpb.TokenReq{ Id: user.ID, GameId: user.GameID, ProjectId: user.ProjectID, LinkId: linkId, IsView: s._isView(), }) 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 = utils.Ternary[int32](s._isView(), mtype.Yes, mtype.No) return } func (s *Visit) _cert(projectId int64) (err error) { if s._isView() { return } // 数据验签 cert, err := app.NewCertifiedFUser().CertUser(s.Ctx, &c_fuserpb.CertUserReq{ ProjectId: projectId, 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) _isView() bool { return s.Req.GetUid() == consts.FissionViewer } func (s *Visit) trace(user *model.GameUser, link *model.GameLink) { if s._isView() { return } app.Redis.Cache.Del(s.Ctx, ckey.GameActionStayId(user.ID, link.ID)) producer.NewCampaignNotice(s.Ctx).GameAction(types.GameAction{ ID: hashid.IdBigint(), ProjectId: user.ProjectID, GameId: user.GameID, UserId: user.ID, LinkId: link.ID, Type: mtype.GameActionTypeVisit, ActionTime: time.Now().Unix(), Dimension: mtype.GameDimension{ GameDimensionOption: mtype.GameDimensionOption{ Ip: s.Req.GetIp(), Os: s.Req.GetOs(), OsVersion: s.Req.GetOsVersion(), DeviceModel: s.Req.GetDeviceModel(), }, }, }) } func (s *Visit) _iovdMark() string { return utils.Md5String(fmt.Sprintf("%s:%s:%s:%s", s.Req.GetIp(), s.Req.GetOs(), s.Req.GetOsVersion(), s.Req.GetDeviceModel())) }