package like import ( "context" "encoding/json" "fmt" "math" "math/rand" "net" "strconv" "time" "go-common/app/interface/main/activity/conf" "go-common/app/interface/main/activity/dao/bnj" "go-common/app/interface/main/activity/dao/like" bnjmdl "go-common/app/interface/main/activity/model/bnj" l "go-common/app/interface/main/activity/model/like" tagrpc "go-common/app/interface/main/tag/rpc/client" accapi "go-common/app/service/main/account/api" arccli "go-common/app/service/main/archive/api" arcrpc "go-common/app/service/main/archive/api/gorpc" arcmdl "go-common/app/service/main/archive/model/archive" coinrpc "go-common/app/service/main/coin/api/gorpc" spymdl "go-common/app/service/main/spy/model" spyrpc "go-common/app/service/main/spy/rpc/client" thumbup "go-common/app/service/main/thumbup/rpc/client" suitrpc "go-common/app/service/main/usersuit/rpc/client" "go-common/library/ecode" "go-common/library/log" "go-common/library/net/metadata" "go-common/library/sync/errgroup" "go-common/library/sync/pipeline/fanout" xtime "go-common/library/time" "github.com/pkg/errors" ) const ( _yes = 1 _no = 0 _typeAll = "all" _typeRegion = "region" _like = "like" _grade = "grade" _vote = "vote" _silenceForbid = 1 ) // Service struct type Service struct { c *conf.Config dao *like.Dao bnjDao *bnj.Dao arcRPC *arcrpc.Service2 arcClient arccli.ArchiveClient coin *coinrpc.Service suit *suitrpc.Service2 accClient accapi.AccountClient spy *spyrpc.Service tagRPC *tagrpc.Service thumbup thumbup.ThumbupRPC cache *fanout.Fanout arcType map[int16]*arcmdl.ArcType dialectTags map[int64]struct{} dialectRegions map[int16]struct{} reward map[int]*bnjmdl.Reward r *rand.Rand newestSubTs int64 } // New Service func New(c *conf.Config) (s *Service) { s = &Service{ c: c, cache: fanout.New("cache", fanout.Worker(1), fanout.Buffer(1024)), dao: like.New(c), bnjDao: bnj.New(c), arcRPC: arcrpc.New2(c.RPCClient2.Archive), coin: coinrpc.New(c.RPCClient2.Coin), suit: suitrpc.New(c.RPCClient2.Suit), spy: spyrpc.New(c.RPCClient2.Spy), tagRPC: tagrpc.New2(c.RPCClient2.Tag), thumbup: thumbup.New(c.RPCClient2.Thumbup), r: rand.New(rand.NewSource(time.Now().UnixNano())), } var err error if s.arcClient, err = arccli.NewClient(c.ArcClient); err != nil { panic(err) } if s.accClient, err = accapi.NewClient(c.AccClient); err != nil { panic(err) } s.initDialect() s.initReward() go s.arcTypeproc() go s.actSourceproc() go s.newestSubTsproc() return } func checkIsLike(subType int64) (likesType bool) { switch subType { case l.PICTURELIKE, l.DRAWYOOLIKE, l.TEXTLIKE, l.VIDEOLIKE, l.VIDEO2, l.VIDEO, l.SMALLVIDEO, l.MUSIC, l.PHONEVIDEO, l.STORYKING: likesType = true default: likesType = false } return } // Subject service func (s *Service) Subject(c context.Context, sid int64) (res *l.Subject, err error) { var ( mc = true subErr error likeErr error ) if res, err = s.dao.InfoCache(c, sid); err != nil { err = nil mc = false } else if res != nil { if res, err = s.LikeArc(c, res); err != nil { return } } eg, errCtx := errgroup.WithContext(c) var ls = make([]*l.Like, 0) eg.Go(func() error { res, subErr = s.dao.Subject(errCtx, sid) return subErr }) eg.Go(func() error { ls, likeErr = s.dao.LikeTypeList(errCtx, sid) return likeErr }) if err = eg.Wait(); err != nil { log.Error("eg.Wait error(%v)", err) return } if res != nil { res.List = ls } if mc { err = s.dao.SetInfoCache(c, res, sid) if err != nil { log.Error("SetInfoCache error(%v)", err) } } if res, err = s.LikeArc(c, res); err != nil { return } return } // LikeArc service func (s *Service) LikeArc(c context.Context, sub *l.Subject) (res *l.Subject, err error) { if sub != nil { if sub.ID == 0 { res = nil } else { res = sub var ( ok bool arcs map[int64]*arccli.Arc aids []int64 ) for _, l := range res.List { aids = append(aids, l.Wid) } argAids := &arcmdl.ArgAids2{ Aids: aids, } if arcs, err = s.arcRPC.Archives3(c, argAids); err != nil { log.Error("s.arcRPC.Archives(arcAids:(%v), arcs), err(%v)", aids, err) return } for _, l := range res.List { if l.Archive, ok = arcs[l.Wid]; !ok { log.Info("s.arcs.wid:(%d),ok(%v)", l.Wid, ok) continue } } } } return } // OnlineVote Service func (s *Service) OnlineVote(c context.Context, mid, vote, stage, aid int64) (res bool, err error) { res = true if vote != _yes && vote != _no { err = nil res = false return } var incrKey string midStr := strconv.FormatInt(mid, 10) aidStr := strconv.FormatInt(aid, 10) stageStr := strconv.FormatInt(stage, 10) midKye := midStr + ":" + aidStr + ":" + stageStr if res, err = s.dao.RsSetNX(c, midKye); err != nil { log.Error("s.OnlineVote.reids(mid:(%v),,vote:(%v),stage:(%v)), err(%v)", mid, vote, stage, err) return } if !res { return } if vote == _yes { incrKey = aidStr + ":" + stageStr + ":yes" } else { incrKey = aidStr + ":" + stageStr + ":no" } if mid == 288239 || mid == 26366366 || mid == 20453897 { log.Info("288239,26366366,20453897") if res, err = s.dao.Incrby(c, incrKey); err != nil { log.Error("s.OnlineVote.Incrby(key:(%v)", incrKey) return } } else { if res, err = s.dao.Incr(c, incrKey); err != nil { log.Error("s.OnlineVote.Incr(key:(%v)", incrKey) return } } s.dao.CVoteLog(c, 0, aid, mid, stage, vote) return } // Ltime service func (s *Service) Ltime(c context.Context, sid int64) (res map[string]interface{}, err error) { var key = "ltime:" + strconv.FormatInt(sid, 10) var b []byte if b, err = s.dao.Rb(c, key); err != nil { log.Error("s.dao.Rb((%v), err(%v)", key, err) return } if b == nil { res = nil return } if err = json.Unmarshal(b, &res); err != nil { log.Error("s.Ltime.Unmarshal((%v), err(%v)", b, err) return } if res["time"] != nil { if st, ok := res["time"].(float64); ok { res["currentTime"] = time.Now().Unix() - int64(st) } } return } // LikeAct service func (s *Service) LikeAct(c context.Context, p *l.ParamAddLikeAct, mid int64) (res int64, err error) { var ( subject *l.SubjectItem likeItem *l.Item memberRly *accapi.ProfileReply subErr error likeErr error ) eg, errCtx := errgroup.WithContext(c) eg.Go(func() error { subject, subErr = s.dao.ActSubject(errCtx, p.Sid) return subErr }) eg.Go(func() error { likeItem, likeErr = s.dao.Like(errCtx, p.Lid) return likeErr }) if err = eg.Wait(); err != nil { log.Error("eg.Wait error(%v)", err) return } if subject.ID == 0 || subject.Type == l.STORYKING { err = ecode.ActivityHasOffLine return } if likeItem.ID == 0 || likeItem.Sid != p.Sid { err = ecode.ActivityLikeHasOffLine return } if memberRly, err = s.accClient.Profile3(c, &accapi.MidReq{Mid: mid}); err != nil { log.Error(" s.acc.Profile3(c,&accmdl.ArgMid{Mid:%d}) error(%v)", mid, err) return } if err = s.judgeUser(c, subject, memberRly.Profile); err != nil { return } nowTime := time.Now().Unix() if int64(memberRly.Profile.JoinTime) >= (nowTime - 86400*7) { err = ecode.ActivityLikeMemberLimit return } if int64(subject.Lstime) >= nowTime { err = ecode.ActivityLikeNotStart return } if int64(subject.Letime) <= nowTime { err = ecode.ActivityLikeHasEnd return } var ( likeAct map[int64]int lids = []int64{p.Lid} ) if likeAct, err = s.dao.LikeActs(c, p.Sid, mid, lids); err != nil { log.Error("s.dao.LikeActMidList(%v) error(%+v)", p, err) return } if _, ok := likeAct[p.Lid]; !ok { log.Error("s.dao.LikeActMidList() get lid value error()") return } isLikeType := s.isLikeType(c, subject.Type) if likeAct[p.Lid] == like.HasLike { if isLikeType == _like { err = ecode.ActivityLikeHasLike } else if isLikeType == _vote { err = ecode.ActivityLikeHasVote } else { err = ecode.ActivityLikeHasGrade } return } var score int64 if isLikeType == _like || isLikeType == _vote { score = l.LIKESCORE } else { score = p.Score } if err = s.dao.SetRedisCache(c, p.Sid, p.Lid, score, likeItem.Type); err != nil { log.Error("s.dao.SetRedisCache(%v) error(%+v)", p, err) return } likeActAdd := &l.Action{ Lid: p.Lid, Mid: mid, Sid: p.Sid, Action: score, IPv6: make([]byte, 0), } if IPv6 := net.ParseIP(metadata.String(c, metadata.RemoteIP)); IPv6 != nil { likeActAdd.IPv6 = IPv6 } if res, err = s.dao.LikeActAdd(c, likeActAdd); err != nil { log.Error("s.dao.LikeActAdd(%v) error(%+v)", p, err) return } s.dao.AddCacheLikeActs(c, p.Sid, mid, map[int64]int{p.Lid: like.HasLike}) return } // StoryKingAct . func (s *Service) StoryKingAct(c context.Context, p *l.ParamStoryKingAct, mid int64) (res map[string]int64, err error) { var ( subject *l.SubjectItem likeItem *l.Item memberRly *accapi.ProfileReply subErr error likeErr error leftTime int64 ) eg, errCtx := errgroup.WithContext(c) eg.Go(func() error { subject, subErr = s.dao.ActSubject(errCtx, p.Sid) return subErr }) eg.Go(func() error { likeItem, likeErr = s.dao.Like(errCtx, p.Lid) return likeErr }) if err = eg.Wait(); err != nil { log.Error("eg.Wait error(%v)", err) return } if subject.ID == 0 || subject.Type != l.STORYKING { err = ecode.ActivityHasOffLine return } if likeItem.ID == 0 || likeItem.Sid != p.Sid { err = ecode.ActivityLikeHasOffLine return } if memberRly, err = s.accClient.Profile3(c, &accapi.MidReq{Mid: mid}); err != nil { log.Error(" s.acc.Profile3(c,&accmdl.ArgMid{Mid:%d}) error(%v)", mid, err) return } if err = s.judgeUser(c, subject, memberRly.Profile); err != nil { return } nowTime := time.Now().Unix() if int64(subject.Lstime) >= nowTime { err = ecode.ActivityLikeNotStart return } if int64(subject.Letime) <= nowTime { err = ecode.ActivityLikeHasEnd return } if leftTime, err = s.storyLikeCheck(c, p.Sid, p.Lid, mid, subject.DailyLikeLimit, subject.DailySingleLikeLimit); err != nil { log.Error(" s.storyLikeCheck(%d,%d,%d) error(%+v)", p.Sid, p.Lid, mid, err) return } if leftTime < p.Score { if leftTime > 0 { p.Score = leftTime } else { err = ecode.ActivityOverDailyScore return } } if err = s.dao.SetRedisCache(c, p.Sid, p.Lid, p.Score, likeItem.Type); err != nil { log.Error("s.dao.SetRedisCache(%v) error(%+v)", p, err) return } likeActAdd := &l.Action{ Lid: p.Lid, Mid: mid, Sid: p.Sid, Action: int64(p.Score), IPv6: make([]byte, 0), } if IPv6 := net.ParseIP(metadata.String(c, metadata.RemoteIP)); IPv6 != nil { likeActAdd.IPv6 = IPv6 } res = make(map[string]int64, 2) if res["act_id"], err = s.dao.LikeActAdd(c, likeActAdd); err != nil { log.Error("s.dao.LikeActAdd(%v) error(%+v)", p, err) return } s.storyLikeActSet(c, p.Sid, p.Lid, mid, p.Score) res["score"] = p.Score return } // StoryKingLeftTime . func (s *Service) StoryKingLeftTime(c context.Context, sid, mid int64) (res int64, err error) { var ( subject *l.SubjectItem memberRly *accapi.ProfileReply ) if subject, err = s.dao.ActSubject(c, sid); err != nil { return } if subject.ID == 0 || subject.Type != l.STORYKING { err = ecode.ActivityHasOffLine return } if memberRly, err = s.accClient.Profile3(c, &accapi.MidReq{Mid: mid}); err != nil { log.Error(" s.acc.Profile3(c,&accmdl.ArgMid{Mid:%d}) error(%v)", mid, err) return } if err = s.simpleJudge(c, subject, memberRly.Profile); err != nil { err = nil res = 0 return } nowTime := time.Now().Unix() if int64(subject.Lstime) >= nowTime || int64(subject.Letime) <= nowTime { res = 0 return } if res, err = s.storySumUsed(c, sid, mid); err != nil { log.Error("s.storySumUsed(%d,%d) error(%+v)", sid, mid, err) return } res = subject.DailyLikeLimit - res if res < 0 { res = 0 } return } // UpList . func (s *Service) UpList(c context.Context, p *l.ParamList, mid int64) (res *l.ListInfo, err error) { switch p.Type { case like.EsOrderLikes, like.EsOrderCoin, like.EsOrderReply, like.EsOrderShare, like.EsOrderClick, like.EsOrderDm, like.EsOrderFav: res, err = s.EsList(c, p, mid) case like.ActOrderCtime, like.ActOrderLike, like.ActOrderRandom: res, err = s.StoryKingList(c, p, mid) default: err = errors.New("type error") } return } // EsList . func (s *Service) EsList(c context.Context, p *l.ParamList, mid int64) (res *l.ListInfo, err error) { var ( subject *l.SubjectItem ) if subject, err = s.dao.ActSubject(c, p.Sid); err != nil { return } if subject.ID == 0 { err = ecode.ActivityHasOffLine return } if res, err = s.dao.ListFromES(c, p.Sid, p.Type, p.Ps, p.Pn, 0); err != nil { log.Error("s.dao.ListFromES(%d) error(%+v)", p.Sid, err) return } if res == nil || len(res.List) == 0 { return } if err = s.getContent(c, res.List, subject.Type, mid, p.Type); err != nil { log.Error("s.getContent(%d) error(%v)", p.Sid, err) } return } // StoryKingList . func (s *Service) StoryKingList(c context.Context, p *l.ParamList, mid int64) (res *l.ListInfo, err error) { var ( subject *l.SubjectItem likeList []*l.List total int64 ) if subject, err = s.dao.ActSubject(c, p.Sid); err != nil { return } if subject.ID == 0 { err = ecode.ActivityHasOffLine return } likesType := checkIsLike(subject.Type) switch p.Type { case like.ActOrderCtime: likeList, err = s.orderByCtime(c, p.Sid, p.Pn, p.Ps, likesType) case like.ActOrderRandom: likeList, err = s.orderByRandom(c, p.Sid, p.Pn, p.Ps, likesType) default: likeList, err = s.orderByLike(c, p.Sid, p.Pn, p.Ps) } if err != nil { log.Error("s.orderBy(%s)(%d) error(%v)", p.Type, p.Sid, err) return } if len(likeList) == 0 { return } if err = s.getContent(c, likeList, subject.Type, mid, p.Type); err != nil { log.Error("s.getContent(%d) error(%v)", p.Sid, err) } if p.Type == like.ActOrderRandom { total, _ = s.dao.LikeRandomCount(c, p.Sid) } else { total, _ = s.dao.LikeCount(c, p.Sid) } res = &l.ListInfo{List: likeList, Page: &l.Page{Size: p.Ps, Num: p.Pn, Total: total}} return } // getContent get likes extends 后期接入其他活动补充完善. func (s *Service) getContent(c context.Context, list []*l.List, subType, mid int64, order string) (err error) { switch subType { case l.STORYKING: err = s.actContent(c, list, mid) case l.PICTURE, l.PICTURELIKE, l.DRAWYOO, l.DRAWYOOLIKE, l.TEXT, l.TEXTLIKE, l.QUESTION: err = s.contentAccount(c, list) case l.VIDEOLIKE, l.VIDEO, l.VIDEO2, l.SMALLVIDEO, l.PHONEVIDEO, l.ONLINEVOTE: err = s.arcTag(c, list, order, mid) default: err = ecode.RequestErr } return } // actContent get like_content and account info. func (s *Service) contentAccount(c context.Context, list []*l.List) (err error) { var ( lt = len(list) lids = make([]int64, 0, lt) mids = make([]int64, 0, lt) cont map[int64]*l.LikeContent actRly *accapi.InfosReply ) for _, v := range list { lids = append(lids, v.ID) if v.Mid > 0 { mids = append(mids, v.Mid) } } eg, errCtx := errgroup.WithContext(c) eg.Go(func() (e error) { cont, e = s.dao.LikeContent(errCtx, lids) return }) eg.Go(func() (e error) { actRly, e = s.accClient.Infos3(errCtx, &accapi.MidsReq{Mids: mids}) return }) if err = eg.Wait(); err != nil { log.Error("actContent:eg.Wait() error(%v)", err) return } for _, v := range list { obj := make(map[string]interface{}, 2) if _, ok := cont[v.ID]; ok { obj["cont"] = cont[v.ID] } if _, k := actRly.Infos[v.Mid]; k { obj["act"] = actRly.Infos[v.Mid] } v.Object = obj } return } // actContent get like_content and account info. func (s *Service) actContent(c context.Context, list []*l.List, mid int64) (err error) { var ( lt = len(list) lids = make([]int64, 0, lt) wids = make([]int64, 0, lt) cont map[int64]*l.LikeContent accRly *accapi.InfosReply ip = metadata.String(c, metadata.RemoteIP) followersRly *accapi.RelationsReply ) for _, v := range list { lids = append(lids, v.ID) if v.Wid > 0 { wids = append(wids, v.Wid) } } eg, errCtx := errgroup.WithContext(c) eg.Go(func() (e error) { cont, e = s.dao.LikeContent(errCtx, lids) return }) eg.Go(func() (e error) { accRly, e = s.accClient.Infos3(errCtx, &accapi.MidsReq{Mids: wids}) return }) if mid > 0 { eg.Go(func() (e error) { followersRly, e = s.accClient.Relations3(errCtx, &accapi.RelationsReq{Mid: mid, Owners: wids, RealIp: ip}) return }) } if err = eg.Wait(); err != nil { log.Error("actContent:eg.Wait() error(%v)", err) return } for _, v := range list { obj := make(map[string]interface{}, 2) if _, ok := cont[v.ID]; ok { obj["cont"] = cont[v.ID] } var t struct { *accapi.Info Following bool `json:"following"` } if _, k := accRly.Infos[v.Wid]; k { t.Info = accRly.Infos[v.Wid] } if mid > 0 { if _, f := followersRly.Relations[v.Wid]; f { t.Following = followersRly.Relations[v.Wid].Following } } obj["act"] = t v.Object = obj } return } // orderByCtime . func (s *Service) orderByCtime(c context.Context, sid int64, pn, ps int, likesType bool) (res []*l.List, err error) { var ( lids []int64 start = (pn - 1) * ps end = start + ps - 1 items map[int64]*l.Item likeAct map[int64]int64 ) if lids, err = s.dao.LikeCtime(c, sid, start, end); err != nil { log.Error("s.dao.LikeCtime(%d,%d,%d) error(%+v)", sid, start, end, err) return } lt := len(lids) if lt == 0 { return } eg, errCtx := errgroup.WithContext(c) eg.Go(func() (e error) { items, e = s.dao.Likes(errCtx, lids) return }) if likesType { eg.Go(func() (e error) { likeAct, e = s.dao.LikeActLidCounts(c, lids) return }) } if err = eg.Wait(); err != nil { log.Error("orderByCtime:eg.Wait() error(%+v)", err) return } res = make([]*l.List, 0, lt) for _, v := range lids { if _, ok := items[v]; ok && items[v].ID > 0 { t := &l.List{Item: items[v]} if likesType { if _, f := likeAct[v]; f { t.Like = likeAct[v] } } res = append(res, t) } else { log.Info("s.dao.CacheLikes(%d) not found", v) } } return } // orderByRandom order by random func (s *Service) orderByRandom(c context.Context, sid int64, pn, ps int, likesType bool) (res []*l.List, err error) { var ( lids []int64 start = (pn - 1) * ps end = start + ps - 1 items map[int64]*l.Item likeAct map[int64]int64 orderIDs []int64 orderList *l.ListInfo ) if lids, err = s.dao.LikeRandom(c, sid, start, end); err != nil { log.Error("s.dao.LikeRandom(%d,%d,%d) error(%+v)", sid, start, end, err) return } lt := len(lids) if lt == 0 { if orderList, err = s.dao.ListFromES(c, sid, "", 500, 1, time.Now().Unix()); err != nil { log.Error("s.dao.ListFromES(%d) error(%+v)", sid, err) return } if orderList == nil || len(orderList.List) == 0 { return } orderLen := len(orderList.List) orderIDs = make([]int64, 0, orderLen) for _, v := range orderList.List { orderIDs = append(orderIDs, v.ID) } if err = s.dao.SetLikeRandom(c, sid, orderIDs); err != nil { log.Error("s.dao.SetLikeRandom(%d) error(%+v)", sid, err) return } if lids, err = s.dao.LikeRandom(c, sid, start, end); err != nil { log.Error("s.dao.LikeRandom(%d,%d,%d) error(%+v)", sid, start, end, err) return } } if len(lids) == 0 { return } eg, errCtx := errgroup.WithContext(c) eg.Go(func() (e error) { items, e = s.dao.Likes(errCtx, lids) return }) if likesType { eg.Go(func() (e error) { likeAct, _ = s.dao.LikeActLidCounts(c, lids) return }) } if err = eg.Wait(); err != nil { log.Error("orderByRandom:eg.Wait() error(%+v)", err) return } res = make([]*l.List, 0, lt) for _, v := range lids { if _, ok := items[v]; ok && items[v].ID > 0 { t := &l.List{Item: items[v]} if likesType { if _, f := likeAct[v]; f { t.Like = likeAct[v] } } res = append(res, t) } else { log.Info("s.dao.orderByRandom(%d) not found", v) } } return } // orderByLike only fo like . func (s *Service) orderByLike(c context.Context, sid int64, pn, ps int) (res []*l.List, err error) { var ( lids []int64 lt int items map[int64]*l.Item start = (pn - 1) * ps end = start + ps - 1 ) infos, err := s.dao.RedisCache(c, sid, start, end) if err != nil { log.Error("s.dao.RedisCache(%d,%d,%d) error(%+v)", sid, start, end, err) return } lt = len(infos) if lt == 0 { return } lids = make([]int64, 0, lt) for _, v := range infos { lids = append(lids, v.Lid) } if items, err = s.dao.Likes(c, lids); err != nil { log.Error("s.dao.CacheLikes(%v) error(%+v)", lids, err) return } res = make([]*l.List, 0, lt) for _, v := range infos { if _, ok := items[v.Lid]; ok && items[v.Lid].ID > 0 { t := &l.List{Item: items[v.Lid], Like: v.Score} res = append(res, t) } else { log.Info("s.dao.CacheLikes(%d) not found", v.Lid) } } return } // storyLikeCheck . func (s *Service) storyLikeCheck(c context.Context, sid, lid, mid, storyMaxAct, storyEachMaxAct int64) (left int64, err error) { var ( sumScore, lScore int64 maxLeft, lLeft int64 ) eg, errCtx := errgroup.WithContext(c) eg.Go(func() (e error) { sumScore, e = s.storySumUsed(errCtx, sid, mid) return }) eg.Go(func() (e error) { lScore, e = s.storyEachUsed(errCtx, sid, mid, lid) return }) if err = eg.Wait(); err != nil { err = errors.Wrap(err, "eg.Wait()") return } maxLeft = storyMaxAct - sumScore lLeft = storyEachMaxAct - lScore left = int64(math.Min(float64(maxLeft), float64(lLeft))) if left <= 0 { left = 0 } return } // storyLikeActSet . func (s *Service) storyLikeActSet(c context.Context, sid, lid, mid int64, score int64) (err error) { eg, errCtx := errgroup.WithContext(c) eg.Go(func() (e error) { _, e = s.dao.IncrStoryLikeSum(errCtx, sid, mid, score) return }) eg.Go(func() (e error) { _, e = s.dao.IncrStoryEachLikeAct(errCtx, sid, mid, lid, score) return }) if err = eg.Wait(); err != nil { log.Error("storyLikeActSet:eg.Wait() error(%+v)", err) } return } // storySumUsed . func (s *Service) storySumUsed(c context.Context, sid, mid int64) (res int64, err error) { if res, err = s.dao.StoryLikeSum(c, sid, mid); err != nil { log.Error("s.dao.StoryLikeSum(%d,%d) error(%+v)", sid, mid, err) return } if res == -1 { today := time.Now().Format("2006-01-02") etime := fmt.Sprintf("%s 23:59:59", today) stime := fmt.Sprintf("%s 00:00:00", today) if res, err = s.dao.StoryLikeActSum(c, sid, mid, stime, etime); err != nil { log.Error("s.dao.StoryLikeActSum(%d,%d) error(%+v)", sid, mid, err) return } if err = s.dao.SetLikeSum(c, sid, mid, res); err != nil { log.Error("s.dao.SetLikeSum(%d,%d,%d) error(%+v)", sid, mid, res, err) } } return } func (s *Service) storyEachUsed(c context.Context, sid, mid, lid int64) (res int64, err error) { if res, err = s.dao.StoryEachLikeSum(c, sid, mid, lid); err != nil { log.Error("s.dao.StoryEachLikeSum(%d,%d) error(%+v)", sid, mid, err) return } if res == -1 { today := time.Now().Format("2006-01-02") etime := fmt.Sprintf("%s 23:59:59", today) stime := fmt.Sprintf("%s 00:00:00", today) if res, err = s.dao.StoryEachLikeAct(c, sid, mid, lid, stime, etime); err != nil { log.Error("s.dao.StoryLikeActSum(%d,%d) error(%+v)", sid, mid, err) return } if err = s.dao.SetEachLikeSum(c, sid, mid, lid, res); err != nil { log.Error("s.dao.SetEachLikeSum(%d,%d,%d) error(%+v)", sid, mid, res, err) } } return } // LikeActList get sid&lid likeact list . func (s *Service) LikeActList(c context.Context, sid, mid int64, lids []int64) (res map[int64]interface{}, err error) { var ( likeCounts map[int64]int64 likeActs map[int64]int likeCount int64 isLike int ) group, ctx := errgroup.WithContext(c) group.Go(func() (e error) { if likeCounts, e = s.dao.LikeActLidCounts(ctx, lids); e != nil { log.Error("s.dao.LikeActLidCounts(%v) error(%+v)", lids, e) return e } return nil }) if mid > 0 { group.Go(func() (e error) { if likeActs, e = s.dao.LikeActs(ctx, sid, mid, lids); e != nil { log.Error("s.dao.LikeActMidList(%v,%d,%d) error(%+v)", lids, sid, mid, e) return e } return nil }) } if err = group.Wait(); err != nil { log.Error("get likeactListerror(%v)", err) return } res = make(map[int64]interface{}, len(lids)) for _, lid := range lids { if _, ok := likeCounts[lid]; ok { likeCount = likeCounts[lid] } else { likeCount = 0 } if _, ok := likeActs[lid]; ok { isLike = likeActs[lid] } else { isLike = 0 } res[lid] = map[string]interface{}{ "likeCount": likeCount, "isLike": isLike, } } return } // isLikeType range liketype find out real type . func (s *Service) isLikeType(c context.Context, subType int64) (res string) { for _, ty := range l.LIKETYPE { if subType == ty { res = _like return } } if subType == l.MUSIC { res = _vote } else { res = _grade } return } // simpleJudge judge user could like or not . func (s *Service) simpleJudge(c context.Context, subject *l.SubjectItem, member *accapi.Profile) (err error) { if member.Silence == _silenceForbid { err = ecode.ActivityMemberBlocked return } if subject.Flag == 0 { return } if (subject.Flag & l.FLAGSPY) == l.FLAGSPY { var userScore *spymdl.UserScore if userScore, err = s.spy.UserScore(c, &spymdl.ArgUserScore{Mid: member.Mid}); err != nil { log.Error("s.spy.UserScore(%d) error(%v)", member.Mid, err) return } if int64(userScore.Score) <= s.c.Rule.Spylike { err = ecode.ActivityLikeScoreLower return } } if (subject.Flag & l.FLAGUSTIME) == l.FLAGUSTIME { if subject.Ustime <= xtime.Time(member.JoinTime) { err = ecode.ActivityLikeRegisterLimit return } } if (subject.Flag & l.FLAGUETIME) == l.FLAGUETIME { if subject.Uetime >= xtime.Time(member.JoinTime) { err = ecode.ActivityLikeBeforeRegister return } } if (subject.Flag & l.FLAGPHONEBIND) == l.FLAGPHONEBIND { if member.TelStatus != 1 { err = ecode.ActivityTelValid return } } if (subject.Flag & l.FLAGLEVEL) == l.FLAGLEVEL { if subject.Level > int64(member.Level) { err = ecode.ActivityLikeLevelLimit } } return } // judgeUser judge user could like or not . func (s *Service) judgeUser(c context.Context, subject *l.SubjectItem, member *accapi.Profile) (err error) { if member.Silence == _silenceForbid { err = ecode.ActivityMemberBlocked return } if subject.Flag == 0 { return } if (subject.Flag & l.FLAGIP) == l.FLAGIP { ip := metadata.String(c, metadata.RemoteIP) var used int if used, err = s.dao.IPReqquestCheck(c, ip); err != nil { log.Error("s.dao.IpReqquestCheck(%s) error(%+v)", ip, err) return } if used == 0 { if err = s.dao.SetIPRequest(c, ip); err != nil { log.Error("s.dao.SetIPRequest(%s) error(%+v)", ip, err) return } } else { err = ecode.ActivityLikeIPFrequence return } } if (subject.Flag & l.FLAGSPY) == l.FLAGSPY { var userScore *spymdl.UserScore if userScore, err = s.spy.UserScore(c, &spymdl.ArgUserScore{Mid: member.Mid}); err != nil { log.Error("s.spy.UserScore(%d) error(%v)", member.Mid, err) return } if int64(userScore.Score) <= s.c.Rule.Spylike { err = ecode.ActivityLikeScoreLower return } } if (subject.Flag & l.FLAGUSTIME) == l.FLAGUSTIME { if subject.Ustime <= xtime.Time(member.JoinTime) { err = ecode.ActivityLikeRegisterLimit return } } if (subject.Flag & l.FLAGUETIME) == l.FLAGUETIME { if subject.Uetime >= xtime.Time(member.JoinTime) { err = ecode.ActivityLikeBeforeRegister return } } if (subject.Flag & l.FLAGPHONEBIND) == l.FLAGPHONEBIND { if member.TelStatus != 1 { err = ecode.ActivityTelValid return } } if (subject.Flag & l.FLAGLEVEL) == l.FLAGLEVEL { if subject.Level > int64(member.Level) { err = ecode.ActivityLikeLevelLimit } } return } // Close service func (s *Service) Close() { s.dao.Close() } // Ping service func (s *Service) Ping(c context.Context) (err error) { err = s.dao.Ping(c) return } func (s *Service) arcTypeproc() { for { if types, err := s.arcRPC.Types2(context.Background()); err != nil { log.Error("s.arcRPC.Types2 error(%v)", err) time.Sleep(time.Second) } else { s.arcType = types } time.Sleep(time.Duration(s.c.Interval.PullArcTypeInterval)) } } func (s *Service) initDialect() { tmpTag := make(map[int64]struct{}, len(s.c.Rule.DialectTags)) for _, v := range s.c.Rule.DialectTags { tmpTag[v] = struct{}{} } tmpRegion := make(map[int16]struct{}, len(s.c.Rule.DialectRegions)) for _, v := range s.c.Rule.DialectRegions { tmpRegion[v] = struct{}{} } s.dialectTags = tmpTag s.dialectRegions = tmpRegion } func (s *Service) actSourceproc() { for { if s.c.Rule.DialectSid != 0 { s.updateActSourceList(context.Background(), s.c.Rule.DialectSid, _typeAll) } if len(s.c.Rule.SpecialSids) > 0 { for _, sid := range s.c.Rule.SpecialSids { if sid > 0 { s.updateActSourceList(context.Background(), sid, _typeRegion) } } } time.Sleep(time.Duration(s.c.Interval.ActSourceInterval)) } } func (s *Service) initReward() { tmp := make(map[int]*bnjmdl.Reward, len(s.c.Bnj2019.Reward)) for _, v := range s.c.Bnj2019.Reward { tmp[v.Step] = v } s.reward = tmp }