go-common/app/interface/main/activity/service/like/service.go
2019-04-22 18:49:16 +08:00

1151 lines
29 KiB
Go

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
}