1219 lines
32 KiB
Go
1219 lines
32 KiB
Go
|
package relation
|
|||
|
|
|||
|
import (
|
|||
|
"context"
|
|||
|
"fmt"
|
|||
|
"hash/crc32"
|
|||
|
"sort"
|
|||
|
"strconv"
|
|||
|
"sync"
|
|||
|
|
|||
|
"go-common/app/interface/main/account/conf"
|
|||
|
"go-common/app/interface/main/account/dao/relation"
|
|||
|
"go-common/app/interface/main/account/model"
|
|||
|
acml "go-common/app/service/main/account/model"
|
|||
|
account "go-common/app/service/main/account/rpc/client"
|
|||
|
archive "go-common/app/service/main/archive/api/gorpc"
|
|||
|
mrl "go-common/app/service/main/relation/model"
|
|||
|
rlrpc "go-common/app/service/main/relation/rpc/client"
|
|||
|
"go-common/library/ecode"
|
|||
|
"go-common/library/log"
|
|||
|
"go-common/library/net/metadata"
|
|||
|
)
|
|||
|
|
|||
|
var (
|
|||
|
_emptyFollowings = []*model.Following{}
|
|||
|
_emptyTagInfos = []*model.Tag{}
|
|||
|
_emptyTags = make(map[int64]string)
|
|||
|
_allTagsStr = "all"
|
|||
|
_specialTagsStr = "special"
|
|||
|
_defaultTagsStr = "default"
|
|||
|
_listTagsStr = "list"
|
|||
|
_emptySpList = []int64{}
|
|||
|
)
|
|||
|
|
|||
|
// Service struct of service.
|
|||
|
type Service struct {
|
|||
|
// conf
|
|||
|
c *conf.Config
|
|||
|
// rpc
|
|||
|
relationRPC *rlrpc.Service
|
|||
|
accountRPC *account.Service3
|
|||
|
archiveRPC *archive.Service2
|
|||
|
// dao
|
|||
|
dao *relation.Dao
|
|||
|
}
|
|||
|
|
|||
|
// New create service instance and return.
|
|||
|
func New(c *conf.Config) (s *Service) {
|
|||
|
s = &Service{
|
|||
|
c: c,
|
|||
|
relationRPC: rlrpc.New(c.RPCClient2.Relation),
|
|||
|
accountRPC: account.New3(c.RPCClient2.Account),
|
|||
|
archiveRPC: archive.New2(c.RPCClient2.Archive),
|
|||
|
dao: relation.New(c),
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Modify modify user relation.
|
|||
|
func (s *Service) Modify(c context.Context, mid, fid int64, act int8, src uint8, ric map[string]string) (err error) {
|
|||
|
if act < mrl.ActAddFollowing || act > mrl.ActDelFollower {
|
|||
|
err = ecode.RequestErr
|
|||
|
return
|
|||
|
}
|
|||
|
arg := &mrl.ArgFollowing{Mid: mid, Fid: fid, Source: src, Action: act, Infoc: ric}
|
|||
|
if err = s.relationRPC.ModifyRelation(c, arg); err != nil {
|
|||
|
log.Error("s.relationRPC.ModifyRelation(mid:%d,fid:%d,src:%d,act:%d) err(%v)", mid, fid, act, src, err)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// BatchModify batch modify user relation.
|
|||
|
func (s *Service) BatchModify(c context.Context, mid int64, fids []int64, act int8, src uint8, ric map[string]string) (result *model.BatchModifyResult, err error) {
|
|||
|
if len(fids) > 50 {
|
|||
|
err = ecode.RequestErr
|
|||
|
return
|
|||
|
}
|
|||
|
for _, fid := range fids {
|
|||
|
if fid <= 0 || fid == mid {
|
|||
|
err = ecode.RequestErr
|
|||
|
return
|
|||
|
}
|
|||
|
}
|
|||
|
// luoweiling: 把非加关注的动作全部拒绝掉
|
|||
|
if act != mrl.ActAddFollowing {
|
|||
|
err = ecode.RequestErr
|
|||
|
return
|
|||
|
}
|
|||
|
if act < mrl.ActAddFollowing || act > mrl.ActDelFollower {
|
|||
|
err = ecode.RequestErr
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// zhangsusu: 批量关注里保持悄悄关注的状态
|
|||
|
whispers, err := s.relationRPC.Whispers(c, &mrl.ArgMid{
|
|||
|
Mid: mid,
|
|||
|
RealIP: "",
|
|||
|
})
|
|||
|
if err != nil {
|
|||
|
log.Error("Failed to get user whispers: mid: %d: %+v", mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
whispersmap := make(map[int64]struct{}, len(whispers))
|
|||
|
for _, w := range whispers {
|
|||
|
whispersmap[w.Mid] = struct{}{}
|
|||
|
}
|
|||
|
filteredFids := make([]int64, 0, len(fids))
|
|||
|
for _, fid := range fids {
|
|||
|
if _, ok := whispersmap[fid]; ok {
|
|||
|
continue
|
|||
|
}
|
|||
|
filteredFids = append(filteredFids, fid)
|
|||
|
}
|
|||
|
|
|||
|
raiseErr := func(in error) error {
|
|||
|
shouldRaise := map[int]struct{}{
|
|||
|
ecode.RelFollowAlreadyBlack.Code(): {},
|
|||
|
ecode.RelFollowReachTelLimit.Code(): {},
|
|||
|
ecode.RelFollowReachMaxLimit.Code(): {},
|
|||
|
}
|
|||
|
ec := ecode.Cause(in)
|
|||
|
if _, ok := shouldRaise[ec.Code()]; ok {
|
|||
|
return ec
|
|||
|
}
|
|||
|
return nil
|
|||
|
}
|
|||
|
|
|||
|
lock := sync.Mutex{}
|
|||
|
result = &model.BatchModifyResult{
|
|||
|
FailedFids: []int64{},
|
|||
|
}
|
|||
|
wg := sync.WaitGroup{}
|
|||
|
for _, fid := range filteredFids {
|
|||
|
fid := fid
|
|||
|
wg.Add(1)
|
|||
|
go func() {
|
|||
|
defer wg.Done()
|
|||
|
|
|||
|
arg := &mrl.ArgFollowing{Mid: mid, Fid: fid, Source: src, Action: act, Infoc: ric}
|
|||
|
rerr := s.relationRPC.ModifyRelation(c, arg)
|
|||
|
if rerr == nil {
|
|||
|
return
|
|||
|
}
|
|||
|
lock.Lock()
|
|||
|
defer lock.Unlock()
|
|||
|
err = raiseErr(rerr)
|
|||
|
log.Error("s.relationRPC.ModifyRelation(mid:%d,fid:%d,src:%d,act:%d) err(%v)", mid, fid, act, src, rerr)
|
|||
|
result.FailedFids = append(result.FailedFids, fid)
|
|||
|
}()
|
|||
|
}
|
|||
|
wg.Wait()
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Relation get user relation.
|
|||
|
func (s *Service) Relation(c context.Context, mid, fid int64) (f *mrl.Following, err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgRelation{Mid: mid, Fid: fid, RealIP: ip}
|
|||
|
if f, err = s.relationRPC.Relation(c, arg); err != nil {
|
|||
|
log.Error("s.Relation(mid %d,fid %d) err(%v)", mid, fid, err)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Relations get relations between users.
|
|||
|
func (s *Service) Relations(c context.Context, mid int64, fids []int64) (f map[int64]*mrl.Following, err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgRelations{Mid: mid, Fids: fids, RealIP: ip}
|
|||
|
if f, err = s.relationRPC.Relations(c, arg); err != nil {
|
|||
|
log.Error("s.Relations(mid %d,fids %d) err(%v)", mid, fids, err)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Blacks get user black list.
|
|||
|
func (s *Service) Blacks(c context.Context, mid int64, version uint64, pn, ps int64) (f []*model.Following, crc32v uint32, total int, err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgMid{Mid: mid, RealIP: ip}
|
|||
|
fr, err := s.relationRPC.Blacks(c, arg)
|
|||
|
if err != nil {
|
|||
|
log.Error("s.Blacks(mid %d) err(%v)", mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
total = len(fr)
|
|||
|
stat, err := s.relationRPC.Stat(c, arg)
|
|||
|
if err != nil {
|
|||
|
log.Error("s.Stat(mid %d) err(%v)", mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
total = int(stat.Black)
|
|||
|
start, end := (pn-1)*ps, pn*ps
|
|||
|
switch {
|
|||
|
case start >= int64(len(fr)):
|
|||
|
fr = fr[:0]
|
|||
|
case end >= int64(len(fr)):
|
|||
|
fr = fr[start:]
|
|||
|
default:
|
|||
|
fr = fr[start:end]
|
|||
|
}
|
|||
|
if len(fr) == 0 {
|
|||
|
f = _emptyFollowings
|
|||
|
return
|
|||
|
}
|
|||
|
temp := []byte(fmt.Sprintf("%s", fr))
|
|||
|
crc32v = crc32.Checksum(temp, crc32.IEEETable)
|
|||
|
if uint64(crc32v) == version {
|
|||
|
err = ecode.NotModified
|
|||
|
return
|
|||
|
}
|
|||
|
var (
|
|||
|
mids []int64
|
|||
|
infos map[int64]*acml.Info
|
|||
|
fi *mrl.Following
|
|||
|
)
|
|||
|
for _, fi = range fr {
|
|||
|
mids = append(mids, fi.Mid)
|
|||
|
}
|
|||
|
accArg := &acml.ArgMids{Mids: mids}
|
|||
|
if infos, err = s.accountRPC.Infos3(c, accArg); err != nil {
|
|||
|
log.Error("s.accountRPC.Infos3(mid:%v) err(%v)", accArg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
for _, fi = range fr {
|
|||
|
tmp := &model.Following{Following: fi}
|
|||
|
info, ok := infos[fi.Mid]
|
|||
|
if !ok {
|
|||
|
log.Warn("Failed to fetch infos with mid: %d", fi.Mid)
|
|||
|
continue
|
|||
|
}
|
|||
|
tmp.Face = info.Face
|
|||
|
tmp.Uname = info.Name
|
|||
|
tmp.Sign = info.Sign
|
|||
|
f = append(f, tmp)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Whispers get user Whispers.
|
|||
|
func (s *Service) Whispers(c context.Context, mid int64, pn, ps int64, version uint64) (f []*model.Following, crc32v uint32, err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgMid{Mid: mid, RealIP: ip}
|
|||
|
fr, err := s.relationRPC.Whispers(c, arg)
|
|||
|
if err != nil {
|
|||
|
log.Error("s.Whispers(mid %d) err(%v)", mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
start, end := (pn-1)*ps, pn*ps
|
|||
|
switch {
|
|||
|
case start >= int64(len(fr)):
|
|||
|
fr = fr[:0]
|
|||
|
case end >= int64(len(fr)):
|
|||
|
fr = fr[start:]
|
|||
|
default:
|
|||
|
fr = fr[start:end]
|
|||
|
}
|
|||
|
if len(fr) == 0 {
|
|||
|
f = _emptyFollowings
|
|||
|
return
|
|||
|
}
|
|||
|
temp := []byte(fmt.Sprintf("%s", fr))
|
|||
|
crc32v = crc32.Checksum(temp, crc32.IEEETable)
|
|||
|
if uint64(crc32v) == version {
|
|||
|
err = ecode.NotModified
|
|||
|
return
|
|||
|
}
|
|||
|
var (
|
|||
|
mids []int64
|
|||
|
cards map[int64]*acml.Card
|
|||
|
fi *mrl.Following
|
|||
|
)
|
|||
|
for _, fi = range fr {
|
|||
|
mids = append(mids, fi.Mid)
|
|||
|
}
|
|||
|
accArg := &acml.ArgMids{Mids: mids}
|
|||
|
if cards, err = s.accountRPC.Cards3(c, accArg); err != nil {
|
|||
|
log.Error("s.accountRPC(mid:%v) err(%v)", accArg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
for _, fi = range fr {
|
|||
|
tmp := &model.Following{Following: fi}
|
|||
|
card, ok := cards[fi.Mid]
|
|||
|
if !ok {
|
|||
|
log.Warn("Failed to fetch card with mid: %d", mid)
|
|||
|
continue
|
|||
|
}
|
|||
|
tmp.Face = card.Face
|
|||
|
tmp.Uname = card.Name
|
|||
|
tmp.Sign = card.Sign
|
|||
|
|
|||
|
of := card.Official
|
|||
|
if of.Role == 0 {
|
|||
|
tmp.OfficialVerify.Type = -1
|
|||
|
} else {
|
|||
|
if of.Role <= 2 {
|
|||
|
tmp.OfficialVerify.Type = 0
|
|||
|
} else {
|
|||
|
tmp.OfficialVerify.Type = 1
|
|||
|
}
|
|||
|
tmp.OfficialVerify.Desc = of.Title
|
|||
|
}
|
|||
|
|
|||
|
// tmp.Vip = cards[fi.Mid].Vip
|
|||
|
tmp.Vip.Type = int(card.Vip.Type)
|
|||
|
tmp.Vip.VipStatus = int(card.Vip.Status)
|
|||
|
tmp.Vip.DueDate = card.Vip.DueDate
|
|||
|
f = append(f, tmp)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Friends get user friends list: follow eachother.
|
|||
|
func (s *Service) Friends(c context.Context, mid int64, version uint64) (f []*model.Following, crc32v uint32, err error) {
|
|||
|
var (
|
|||
|
mids []int64
|
|||
|
cards map[int64]*acml.Card
|
|||
|
fi *mrl.Following
|
|||
|
fo, fs []*mrl.Following
|
|||
|
ip = metadata.String(c, metadata.RemoteIP)
|
|||
|
)
|
|||
|
arg := &mrl.ArgMid{Mid: mid, RealIP: ip}
|
|||
|
if fo, err = s.relationRPC.Followings(c, arg); err != nil {
|
|||
|
log.Error("s.Followings(mid %d) err(%v)", mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
for _, fi = range fo {
|
|||
|
if mrl.Attr(fi.Attribute) == mrl.AttrFriend {
|
|||
|
fs = append(fs, fi)
|
|||
|
}
|
|||
|
}
|
|||
|
if len(fs) == 0 {
|
|||
|
f = _emptyFollowings
|
|||
|
return
|
|||
|
}
|
|||
|
temp := []byte(fmt.Sprintf("%s", fo))
|
|||
|
crc32v = crc32.Checksum(temp, crc32.IEEETable)
|
|||
|
if uint64(crc32v) == version {
|
|||
|
err = ecode.NotModified
|
|||
|
return
|
|||
|
}
|
|||
|
for _, fi = range fs {
|
|||
|
mids = append(mids, fi.Mid)
|
|||
|
}
|
|||
|
accArg := &acml.ArgMids{Mids: mids}
|
|||
|
if cards, err = s.accountRPC.Cards3(c, accArg); err != nil {
|
|||
|
log.Error("s.accountRPC.Cards3(mid:%v) err(%v)", accArg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
for _, fi = range fs {
|
|||
|
tmp := &model.Following{Following: fi}
|
|||
|
card, ok := cards[fi.Mid]
|
|||
|
if !ok {
|
|||
|
log.Warn("Failed to fetch card with mid: %d", fi.Mid)
|
|||
|
continue
|
|||
|
}
|
|||
|
tmp.Face = card.Face
|
|||
|
tmp.Uname = card.Name
|
|||
|
tmp.Sign = card.Sign
|
|||
|
// tmp.OfficialVerify = cards[fi.Mid].Official
|
|||
|
of := card.Official
|
|||
|
if of.Role == 0 {
|
|||
|
tmp.OfficialVerify.Type = -1
|
|||
|
} else {
|
|||
|
if of.Role <= 2 {
|
|||
|
tmp.OfficialVerify.Type = 0
|
|||
|
} else {
|
|||
|
tmp.OfficialVerify.Type = 1
|
|||
|
}
|
|||
|
tmp.OfficialVerify.Desc = of.Title
|
|||
|
}
|
|||
|
|
|||
|
// tmp.Vip = infos[fi.Mid].Vip
|
|||
|
tmp.Vip.Type = int(card.Vip.Type)
|
|||
|
tmp.Vip.VipStatus = int(card.Vip.Status)
|
|||
|
tmp.Vip.DueDate = card.Vip.DueDate
|
|||
|
f = append(f, tmp)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Followers get user followings.
|
|||
|
func (s *Service) Followers(c context.Context, vmid, mid, pn, ps int64, version uint64) (f []*model.Following, crc32v uint32, total int, err error) {
|
|||
|
var (
|
|||
|
mids []int64
|
|||
|
cards map[int64]*acml.Card
|
|||
|
fi *mrl.Following
|
|||
|
ip = metadata.String(c, metadata.RemoteIP)
|
|||
|
)
|
|||
|
arg := &mrl.ArgMid{Mid: vmid, RealIP: ip}
|
|||
|
fr, err := s.relationRPC.Followers(c, arg)
|
|||
|
if err != nil {
|
|||
|
log.Error("s.Followers(mid %d) err(%v)", vmid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
stat, err := s.relationRPC.Stat(c, arg)
|
|||
|
if err != nil {
|
|||
|
log.Error("s.Stat(mid %d) err(%v)", vmid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
total = int(stat.Follower)
|
|||
|
start, end := (pn-1)*ps, pn*ps
|
|||
|
switch {
|
|||
|
case start >= int64(len(fr)):
|
|||
|
fr = fr[:0]
|
|||
|
case end >= int64(len(fr)):
|
|||
|
fr = fr[start:]
|
|||
|
default:
|
|||
|
fr = fr[start:end]
|
|||
|
}
|
|||
|
if len(fr) == 0 {
|
|||
|
f = _emptyFollowings
|
|||
|
return
|
|||
|
}
|
|||
|
for _, fi = range fr {
|
|||
|
mids = append(mids, fi.Mid)
|
|||
|
}
|
|||
|
// !self, compute !self user and up's followings' attr
|
|||
|
var frs map[int64]*mrl.Following
|
|||
|
if mid != 0 {
|
|||
|
argfrs := &mrl.ArgRelations{Mid: mid, Fids: mids, RealIP: ip}
|
|||
|
frs, err = s.relationRPC.Relations(c, argfrs)
|
|||
|
if err != nil {
|
|||
|
log.Error("s.relationRPC.Relations(c, %v) error(%v)", argfrs, err)
|
|||
|
return
|
|||
|
}
|
|||
|
}
|
|||
|
temp := []byte(fmt.Sprintf("%s", fr))
|
|||
|
crc32v = crc32.Checksum(temp, crc32.IEEETable)
|
|||
|
if uint64(crc32v) == version {
|
|||
|
err = ecode.NotModified
|
|||
|
return
|
|||
|
}
|
|||
|
accArg := &acml.ArgMids{Mids: mids}
|
|||
|
if cards, err = s.accountRPC.Cards3(c, accArg); err != nil {
|
|||
|
log.Error("s.accountRPC.Cards3(mid:%v) err(%v)", accArg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
for _, fi = range fr {
|
|||
|
tmp := &model.Following{Following: fi}
|
|||
|
card, ok := cards[fi.Mid]
|
|||
|
if !ok {
|
|||
|
log.Warn("Failed to fetch card with mid: %d", mid)
|
|||
|
continue
|
|||
|
}
|
|||
|
tmp.Face = card.Face
|
|||
|
tmp.Uname = card.Name
|
|||
|
tmp.Sign = card.Sign
|
|||
|
if frst, ok := frs[fi.Mid]; ok {
|
|||
|
tmp.Attribute = frst.Attribute
|
|||
|
} else {
|
|||
|
tmp.Attribute = mrl.AttrNoRelation
|
|||
|
}
|
|||
|
// tmp.OfficialVerify = cards[fi.Mid].Official
|
|||
|
of := card.Official
|
|||
|
if of.Role == 0 {
|
|||
|
tmp.OfficialVerify.Type = -1
|
|||
|
} else {
|
|||
|
if of.Role <= 2 {
|
|||
|
tmp.OfficialVerify.Type = 0
|
|||
|
} else {
|
|||
|
tmp.OfficialVerify.Type = 1
|
|||
|
}
|
|||
|
tmp.OfficialVerify.Desc = of.Title
|
|||
|
}
|
|||
|
|
|||
|
// tmp.Vip = infos[fi.Mid].Vip
|
|||
|
tmp.Vip.Type = int(card.Vip.Type)
|
|||
|
tmp.Vip.VipStatus = int(card.Vip.Status)
|
|||
|
tmp.Vip.DueDate = card.Vip.DueDate
|
|||
|
f = append(f, tmp)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Followings get user followings list.
|
|||
|
func (s *Service) Followings(c context.Context, vmid, mid, pn, ps int64, version uint64, order string) (f []*model.Following, crc32v uint32, total int, err error) {
|
|||
|
var (
|
|||
|
mids []int64
|
|||
|
cards map[int64]*acml.Card
|
|||
|
fi *mrl.Following
|
|||
|
ip = metadata.String(c, metadata.RemoteIP)
|
|||
|
)
|
|||
|
arg := &mrl.ArgMid{Mid: vmid, RealIP: ip}
|
|||
|
fr, err := s.relationRPC.Followings(c, arg)
|
|||
|
if err != nil {
|
|||
|
log.Error("s.Followings(mid %d) err(%v)", vmid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
stat, err := s.relationRPC.Stat(c, arg)
|
|||
|
if err != nil {
|
|||
|
log.Error("s.Stat(mid %d) err(%v)", vmid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
total = int(stat.Following)
|
|||
|
if order == "asc" {
|
|||
|
sort.Sort(ByMTime(fr))
|
|||
|
}
|
|||
|
start, end := (pn-1)*ps, pn*ps
|
|||
|
switch {
|
|||
|
case start >= int64(len(fr)):
|
|||
|
fr = fr[:0]
|
|||
|
case end >= int64(len(fr)):
|
|||
|
fr = fr[start:]
|
|||
|
default:
|
|||
|
fr = fr[start:end]
|
|||
|
}
|
|||
|
if len(fr) == 0 {
|
|||
|
f = _emptyFollowings
|
|||
|
return
|
|||
|
}
|
|||
|
for _, fi = range fr {
|
|||
|
mids = append(mids, fi.Mid)
|
|||
|
}
|
|||
|
// !self, compute !self user and up's followings' attr
|
|||
|
var frs map[int64]*mrl.Following
|
|||
|
if mid != vmid && mid != 0 {
|
|||
|
argfrs := &mrl.ArgRelations{Mid: mid, Fids: mids, RealIP: ip}
|
|||
|
frs, err = s.relationRPC.Relations(c, argfrs)
|
|||
|
if err != nil {
|
|||
|
log.Error("s.relationRPC.Relations(c, %v) error(%v)", argfrs, err)
|
|||
|
return
|
|||
|
}
|
|||
|
}
|
|||
|
temp := []byte(fmt.Sprintf("%s", fr))
|
|||
|
crc32v = crc32.Checksum(temp, crc32.IEEETable)
|
|||
|
if uint64(crc32v) == version {
|
|||
|
err = ecode.NotModified
|
|||
|
return
|
|||
|
}
|
|||
|
accArg := &acml.ArgMids{Mids: mids}
|
|||
|
if cards, err = s.accountRPC.Cards3(c, accArg); err != nil {
|
|||
|
log.Error("s.accountRPC.Cards3(mid:%v) err(%v)", accArg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
for _, fi = range fr {
|
|||
|
tmp := &model.Following{Following: fi}
|
|||
|
card, ok := cards[fi.Mid]
|
|||
|
if !ok {
|
|||
|
log.Warn("Failed to fetch card with mid: %d", mid)
|
|||
|
continue
|
|||
|
}
|
|||
|
tmp.Face = card.Face
|
|||
|
tmp.Uname = card.Name
|
|||
|
tmp.Sign = card.Sign
|
|||
|
if mid != vmid {
|
|||
|
if frst, ok := frs[fi.Mid]; ok {
|
|||
|
tmp.Attribute = frst.Attribute
|
|||
|
} else {
|
|||
|
tmp.Attribute = mrl.AttrNoRelation
|
|||
|
}
|
|||
|
}
|
|||
|
// tmp.OfficialVerify = cards[fi.Mid].Official
|
|||
|
of := card.Official
|
|||
|
if of.Role == 0 {
|
|||
|
tmp.OfficialVerify.Type = -1
|
|||
|
} else {
|
|||
|
if of.Role <= 2 {
|
|||
|
tmp.OfficialVerify.Type = 0
|
|||
|
} else {
|
|||
|
tmp.OfficialVerify.Type = 1
|
|||
|
}
|
|||
|
tmp.OfficialVerify.Desc = of.Title
|
|||
|
}
|
|||
|
|
|||
|
// tmp.Vip = infos[fi.Mid].Vip
|
|||
|
tmp.Vip.Type = int(card.Vip.Type)
|
|||
|
tmp.Vip.VipStatus = int(card.Vip.Status)
|
|||
|
tmp.Vip.DueDate = card.Vip.DueDate
|
|||
|
f = append(f, tmp)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Stat get user relation stat.
|
|||
|
func (s *Service) Stat(c context.Context, mid int64, self bool) (st *mrl.Stat, err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgMid{Mid: mid, RealIP: ip}
|
|||
|
if st, err = s.relationRPC.Stat(c, arg); err != nil {
|
|||
|
log.Error("s.Stat(mid %d) err(%v)", mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
if !self {
|
|||
|
st.Whisper = 0
|
|||
|
st.Black = 0
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Stats get users relation stat.
|
|||
|
func (s *Service) Stats(c context.Context, mids []int64) (st map[int64]*mrl.Stat, err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgMids{Mids: mids, RealIP: ip}
|
|||
|
return s.relationRPC.Stats(c, arg)
|
|||
|
}
|
|||
|
|
|||
|
// Ping check server ok.
|
|||
|
func (s *Service) Ping(c context.Context) (err error) {
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// ByMTime implements sort.Interface for []model.Following based on the MTime field.
|
|||
|
type ByMTime []*mrl.Following
|
|||
|
|
|||
|
func (mt ByMTime) Len() int { return len(mt) }
|
|||
|
func (mt ByMTime) Swap(i, j int) { mt[i], mt[j] = mt[j], mt[i] }
|
|||
|
func (mt ByMTime) Less(i, j int) bool { return mt[i].MTime < mt[j].MTime }
|
|||
|
|
|||
|
// Tag get tag info by tag.
|
|||
|
func (s *Service) Tag(c context.Context, mid int64, tagid int64, pn int64, ps int64) (tagInfo []*model.Tag, err error) {
|
|||
|
var (
|
|||
|
mids []int64
|
|||
|
cards map[int64]*acml.Card
|
|||
|
ip = metadata.String(c, metadata.RemoteIP)
|
|||
|
)
|
|||
|
arg := &mrl.ArgTagId{Mid: mid, TagId: tagid, RealIP: ip}
|
|||
|
if mids, err = s.relationRPC.Tag(c, arg); err != nil {
|
|||
|
log.Error("s.relationRPC(%d).Arg(%v) error(%v)", mid, arg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
var tmpMids []int64
|
|||
|
start, end := (pn-1)*ps, pn*ps
|
|||
|
switch {
|
|||
|
case start >= int64(len(mids)):
|
|||
|
tmpMids = mids[:0]
|
|||
|
case end >= int64(len(mids)):
|
|||
|
tmpMids = mids[start:]
|
|||
|
default:
|
|||
|
tmpMids = mids[start:end]
|
|||
|
}
|
|||
|
if len(tmpMids) == 0 {
|
|||
|
tagInfo = _emptyTagInfos
|
|||
|
return
|
|||
|
}
|
|||
|
accArg := &acml.ArgMids{Mids: mids}
|
|||
|
if cards, err = s.accountRPC.Cards3(c, accArg); err != nil {
|
|||
|
log.Error("s.accountRPC.Cards3(mid:%v) err(%v)", accArg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
for _, mid = range tmpMids {
|
|||
|
tmp := &model.Tag{Mid: mid}
|
|||
|
card, ok := cards[mid]
|
|||
|
if !ok {
|
|||
|
log.Warn("Failed to fetch card with mid: %d", mid)
|
|||
|
continue
|
|||
|
}
|
|||
|
tmp.Mid = mid
|
|||
|
tmp.Face = card.Face
|
|||
|
tmp.Uname = card.Name
|
|||
|
tmp.Sign = card.Sign
|
|||
|
// tmp.OfficialVerify = cards[mid].Official
|
|||
|
of := card.Official
|
|||
|
if of.Role == 0 {
|
|||
|
tmp.OfficialVerify.Type = -1
|
|||
|
} else {
|
|||
|
if of.Role <= 2 {
|
|||
|
tmp.OfficialVerify.Type = 0
|
|||
|
} else {
|
|||
|
tmp.OfficialVerify.Type = 1
|
|||
|
}
|
|||
|
tmp.OfficialVerify.Desc = of.Title
|
|||
|
}
|
|||
|
// tmp.Vip = infos[mid].Vip
|
|||
|
tmp.Vip.Type = int(card.Vip.Type)
|
|||
|
tmp.Vip.VipStatus = int(card.Vip.Status)
|
|||
|
tmp.Vip.DueDate = card.Vip.DueDate
|
|||
|
tagInfo = append(tagInfo, tmp)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Tags is.
|
|||
|
func (s *Service) Tags(c context.Context, mid int64) (tagsCount []*mrl.TagCount, err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgMid{Mid: mid, RealIP: ip}
|
|||
|
if tagsCount, err = s.relationRPC.Tags(c, arg); err != nil {
|
|||
|
log.Error("s.relationRPC(%d).Arg(%v) error(%v)", mid, arg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// MobileTags is.
|
|||
|
func (s *Service) MobileTags(c context.Context, mid int64) (tagsCount map[string][]*mrl.TagCount, err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgMid{Mid: mid, RealIP: ip}
|
|||
|
tags, err := s.relationRPC.Tags(c, arg)
|
|||
|
if err != nil {
|
|||
|
log.Error("s.relationRPC(%d).Arg(%v) error(%v)", mid, arg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
var st *mrl.Stat
|
|||
|
argStat := &mrl.ArgMid{Mid: mid, RealIP: ip}
|
|||
|
if st, err = s.relationRPC.Stat(c, argStat); err != nil {
|
|||
|
log.Error("s.Stat(mid %d) err(%v)", mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
tagsCount = map[string][]*mrl.TagCount{
|
|||
|
_allTagsStr: {{
|
|||
|
Tagid: -1,
|
|||
|
Name: "公开关注",
|
|||
|
Count: st.Following,
|
|||
|
}},
|
|||
|
_specialTagsStr: {{
|
|||
|
Tagid: -10,
|
|||
|
Name: "特别关注",
|
|||
|
Count: 0,
|
|||
|
}},
|
|||
|
_listTagsStr: make([]*mrl.TagCount, 0, len(tags)),
|
|||
|
_defaultTagsStr: make([]*mrl.TagCount, 0, 1),
|
|||
|
}
|
|||
|
for _, v := range tags {
|
|||
|
if v.Tagid == 0 {
|
|||
|
tagsCount[_defaultTagsStr] = append(tagsCount[_defaultTagsStr], v)
|
|||
|
} else if v.Tagid == -10 {
|
|||
|
tagsCount[_specialTagsStr][0].Count = v.Count
|
|||
|
} else {
|
|||
|
tagsCount[_listTagsStr] = append(tagsCount[_listTagsStr], v)
|
|||
|
}
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// UserTag is.
|
|||
|
func (s *Service) UserTag(c context.Context, mid int64, fid int64) (tags map[int64]string, err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgRelation{Mid: mid, Fid: fid, RealIP: ip}
|
|||
|
if tags, err = s.relationRPC.UserTag(c, arg); err != nil {
|
|||
|
log.Error("s.relationRPC.Arg(%v) error(%v)", arg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
if tags == nil {
|
|||
|
tags = _emptyTags
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// CreateTag is.
|
|||
|
func (s *Service) CreateTag(c context.Context, mid int64, tag string) (tagInfo int64, err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgTag{Mid: mid, Tag: tag, RealIP: ip}
|
|||
|
if tagInfo, err = s.relationRPC.CreateTag(c, arg); err != nil {
|
|||
|
log.Error("s.relationRPC.Arg(%v) error(%v)", arg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// UpdateTag is.
|
|||
|
func (s *Service) UpdateTag(c context.Context, mid int64, tagID int64, new string) (err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgTagUpdate{Mid: mid, TagId: tagID, New: new, RealIP: ip}
|
|||
|
if err = s.relationRPC.UpdateTag(c, arg); err != nil {
|
|||
|
log.Error("s.relationRPC.Arg(%v) error(%v)", arg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// DelTag is.
|
|||
|
func (s *Service) DelTag(c context.Context, mid int64, tagID int64) (err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgTagDel{Mid: mid, TagId: tagID, RealIP: ip}
|
|||
|
if err = s.relationRPC.DelTag(c, arg); err != nil {
|
|||
|
log.Error("s.relationRPC.Arg(%v) error(%v)", arg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// TagsAddUsers is.
|
|||
|
func (s *Service) TagsAddUsers(c context.Context, mid int64, tagIds string, fids string) (err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgTagsMoveUsers{Mid: mid, BeforeID: 0, AfterTagIds: tagIds, Fids: fids, RealIP: ip}
|
|||
|
if err = s.relationRPC.TagsAddUsers(c, arg); err != nil {
|
|||
|
log.Error("s.relationRPC.Arg(%v) error(%v)", arg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// TagsCopyUsers is.
|
|||
|
func (s *Service) TagsCopyUsers(c context.Context, mid int64, tagIds string, fids string) (err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgTagsMoveUsers{Mid: mid, BeforeID: 0, AfterTagIds: tagIds, Fids: fids, RealIP: ip}
|
|||
|
if err = s.relationRPC.TagsCopyUsers(c, arg); err != nil {
|
|||
|
log.Error("s.relationRPC.Arg(%v) error(%v)", arg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// TagsMoveUsers is.
|
|||
|
func (s *Service) TagsMoveUsers(c context.Context, mid, beforeid int64, afterTagIdsStr, fidsStr string) (err error) {
|
|||
|
ip := metadata.String(c, metadata.RemoteIP)
|
|||
|
arg := &mrl.ArgTagsMoveUsers{Mid: mid, BeforeID: beforeid, AfterTagIds: afterTagIdsStr, Fids: fidsStr, RealIP: ip}
|
|||
|
if err = s.relationRPC.TagsMoveUsers(c, arg); err != nil {
|
|||
|
log.Error("s.relationRPC.Arg(%v) error(%v)", arg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Prompt report and get prompt status.
|
|||
|
func (s *Service) Prompt(c context.Context, arg *mrl.ArgPrompt) (b bool, err error) {
|
|||
|
return s.relationRPC.Prompt(c, arg)
|
|||
|
}
|
|||
|
|
|||
|
// ClosePrompt close prompt.
|
|||
|
func (s *Service) ClosePrompt(c context.Context, arg *mrl.ArgPrompt) (err error) {
|
|||
|
return s.relationRPC.ClosePrompt(c, arg)
|
|||
|
}
|
|||
|
|
|||
|
// AddSpecial add fid into special.
|
|||
|
func (s *Service) AddSpecial(c context.Context, arg *mrl.ArgFollowing) (err error) {
|
|||
|
return s.relationRPC.AddSpecial(c, arg)
|
|||
|
}
|
|||
|
|
|||
|
// DelSpecial del fid from sepcial.
|
|||
|
func (s *Service) DelSpecial(c context.Context, arg *mrl.ArgFollowing) (err error) {
|
|||
|
return s.relationRPC.DelSpecial(c, arg)
|
|||
|
}
|
|||
|
|
|||
|
// Special get user special list.
|
|||
|
func (s *Service) Special(c context.Context, mid int64) (l []int64, err error) {
|
|||
|
arg := &mrl.ArgMid{
|
|||
|
Mid: mid,
|
|||
|
}
|
|||
|
l, err = s.relationRPC.Special(c, arg)
|
|||
|
if len(l) == 0 {
|
|||
|
l = _emptySpList
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Unread check unread status, for the 'show red point' function.
|
|||
|
func (s *Service) Unread(c context.Context, mid int64, disableAutoReset bool) (show bool, err error) {
|
|||
|
arg := &mrl.ArgMid{
|
|||
|
Mid: mid,
|
|||
|
}
|
|||
|
// if !disableAutoReset {
|
|||
|
// defer s.ResetUnread(c, mid)
|
|||
|
// }
|
|||
|
return s.relationRPC.FollowersUnread(c, arg)
|
|||
|
}
|
|||
|
|
|||
|
// ResetUnread is
|
|||
|
func (s *Service) ResetUnread(c context.Context, mid int64) (err error) {
|
|||
|
arg := &mrl.ArgMid{
|
|||
|
Mid: mid,
|
|||
|
}
|
|||
|
return s.relationRPC.ResetFollowersUnread(c, arg)
|
|||
|
}
|
|||
|
|
|||
|
// UnreadCount unread count.
|
|||
|
func (s *Service) UnreadCount(c context.Context, mid int64, disableAutoReset bool) (count int64, err error) {
|
|||
|
arg := &mrl.ArgMid{
|
|||
|
Mid: mid,
|
|||
|
}
|
|||
|
// if !disableAutoReset {
|
|||
|
// defer func() {
|
|||
|
// s.ResetUnread(c, mid)
|
|||
|
// s.ResetUnreadCount(c, mid)
|
|||
|
// }()
|
|||
|
// }
|
|||
|
return s.relationRPC.FollowersUnreadCount(c, arg)
|
|||
|
}
|
|||
|
|
|||
|
// ResetUnreadCount is
|
|||
|
func (s *Service) ResetUnreadCount(c context.Context, mid int64) (err error) {
|
|||
|
arg := &mrl.ArgMid{
|
|||
|
Mid: mid,
|
|||
|
}
|
|||
|
return s.relationRPC.ResetFollowersUnreadCount(c, arg)
|
|||
|
}
|
|||
|
|
|||
|
// RecommendTagSuggestDetail is
|
|||
|
func (s *Service) RecommendTagSuggestDetail(c context.Context, arg *model.ArgTagSuggestRecommend) (*model.TagSuggestRecommendInfo, error) {
|
|||
|
result, err := s.RecommendTagSuggest(c, arg)
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
if len(result) <= 0 {
|
|||
|
empty := &model.TagSuggestRecommendInfo{
|
|||
|
TagName: arg.TagName,
|
|||
|
UpList: []*model.RecommendInfo{},
|
|||
|
MatchCnt: 0,
|
|||
|
}
|
|||
|
return empty, nil
|
|||
|
}
|
|||
|
detail := result[0]
|
|||
|
|
|||
|
upMids := func() []int64 {
|
|||
|
mids := make([]int64, 0, len(detail.UpList))
|
|||
|
for _, up := range detail.UpList {
|
|||
|
mid, perr := strconv.ParseInt(up.Mid, 10, 64)
|
|||
|
if perr != nil {
|
|||
|
log.Warn("Failed to parse mid: %s: %+v", up.Mid, perr)
|
|||
|
continue
|
|||
|
}
|
|||
|
mids = append(mids, mid)
|
|||
|
}
|
|||
|
return mids
|
|||
|
}()
|
|||
|
|
|||
|
rels, err := s.relationRPC.Relations(c, &mrl.ArgRelations{
|
|||
|
Mid: arg.Mid,
|
|||
|
Fids: upMids,
|
|||
|
RealIP: arg.RemoteIP,
|
|||
|
})
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
for _, up := range detail.UpList {
|
|||
|
mid, err := strconv.ParseInt(up.Mid, 10, 64)
|
|||
|
if err != nil {
|
|||
|
log.Warn("Failed to parse mid: %s: %+v", err, up.Mid)
|
|||
|
continue
|
|||
|
}
|
|||
|
r, ok := rels[mid]
|
|||
|
if !ok {
|
|||
|
log.Warn("Failed to get relation between %d and %d", arg.Mid, mid)
|
|||
|
up.Relation = &mrl.Following{Mid: mid} // empty relation
|
|||
|
continue
|
|||
|
}
|
|||
|
up.Relation = r
|
|||
|
}
|
|||
|
|
|||
|
return detail, nil
|
|||
|
}
|
|||
|
|
|||
|
// RecommendTagSuggest is
|
|||
|
func (s *Service) RecommendTagSuggest(c context.Context, arg *model.ArgTagSuggestRecommend) ([]*model.TagSuggestRecommendInfo, error) {
|
|||
|
resp, err := s.dao.TagSuggestRecommend(c, arg.Mid, arg.ContextID, arg.TagName, arg.Device, arg.PageSize, arg.RemoteIP)
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
|
|||
|
allrecs := make([]*model.RecommendContent, 0)
|
|||
|
for _, rec := range resp.Data {
|
|||
|
allrecs = append(allrecs, rec.UpList...)
|
|||
|
}
|
|||
|
allrecinfos, err := s.collectionAsRecommendUserInfo(c, allrecs, resp.TrackID, arg.RemoteIP)
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
allrecinfomap := make(map[string]*model.RecommendInfo, len(allrecinfos))
|
|||
|
for _, recinfo := range allrecinfos {
|
|||
|
allrecinfomap[recinfo.Mid] = recinfo
|
|||
|
}
|
|||
|
|
|||
|
getRecInfos := func(mids ...int64) []*model.RecommendInfo {
|
|||
|
out := make([]*model.RecommendInfo, 0, len(mids))
|
|||
|
for _, mid := range mids {
|
|||
|
smid := strconv.FormatInt(mid, 10)
|
|||
|
recinfo, ok := allrecinfomap[smid]
|
|||
|
if !ok {
|
|||
|
log.Warn("Failed to get user info with mid: %d", mid)
|
|||
|
continue
|
|||
|
}
|
|||
|
out = append(out, recinfo)
|
|||
|
}
|
|||
|
return out
|
|||
|
}
|
|||
|
|
|||
|
result := make([]*model.TagSuggestRecommendInfo, 0, len(resp.Data))
|
|||
|
for _, rec := range resp.Data {
|
|||
|
trecinfo := &model.TagSuggestRecommendInfo{
|
|||
|
TagName: rec.TagName,
|
|||
|
MatchCnt: rec.MatchCnt,
|
|||
|
}
|
|||
|
rinfos := getRecInfos(rec.UpIDs()...)
|
|||
|
trecinfo.UpList = rinfos
|
|||
|
if len(rinfos) != len(rec.UpIDs()) {
|
|||
|
log.Warn("Inconsistent user info and recommend match count: %d, %d", len(rinfos), len(rec.UpIDs()))
|
|||
|
trecinfo.MatchCnt -= int64(len(rec.UpIDs()) - len(rinfos))
|
|||
|
}
|
|||
|
result = append(result, trecinfo)
|
|||
|
}
|
|||
|
return result, nil
|
|||
|
}
|
|||
|
|
|||
|
// RecommendFollowlistEmpty is
|
|||
|
func (s *Service) RecommendFollowlistEmpty(c context.Context, arg *model.ArgRecommend) ([]*model.RecommendInfo, error) {
|
|||
|
return s.recommend(c, "followlist_empty", arg)
|
|||
|
}
|
|||
|
|
|||
|
// RecommendAnswerOK is
|
|||
|
func (s *Service) RecommendAnswerOK(c context.Context, arg *model.ArgRecommend) ([]*model.RecommendInfo, error) {
|
|||
|
return s.recommend(c, "answer_ok", arg)
|
|||
|
}
|
|||
|
|
|||
|
func (s *Service) collectionAsRecommendUserInfo(c context.Context, recs []*model.RecommendContent, trackID string, ip string) ([]*model.RecommendInfo, error) {
|
|||
|
recmap := make(map[int64]*model.RecommendContent, len(recs))
|
|||
|
mids := make([]int64, 0, len(recs))
|
|||
|
for _, r := range recs {
|
|||
|
mids = append(mids, r.UpID)
|
|||
|
recmap[r.UpID] = r
|
|||
|
}
|
|||
|
|
|||
|
cards, err := s.accountRPC.Cards3(c, &acml.ArgMids{Mids: mids})
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
|
|||
|
stats, err := s.relationRPC.Stats(c, &mrl.ArgMids{Mids: mids, RealIP: ip})
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
|
|||
|
// TODO: cache types
|
|||
|
types, err := s.archiveRPC.Types2(c)
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
typeName := func(tid int16) string {
|
|||
|
t := types[tid]
|
|||
|
if t == nil {
|
|||
|
return ""
|
|||
|
}
|
|||
|
return t.Name
|
|||
|
}
|
|||
|
|
|||
|
ris := make([]*model.RecommendInfo, 0, len(recs))
|
|||
|
for _, rec := range recs {
|
|||
|
if rec == nil {
|
|||
|
log.Warn("Invalid recommend content: %+v", rec)
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
card, ok := cards[rec.UpID]
|
|||
|
if !ok {
|
|||
|
log.Warn("Failed to get user card with mid: %d", rec.UpID)
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
stat, ok := stats[rec.UpID]
|
|||
|
if !ok {
|
|||
|
log.Warn("Failed to get stat with mid: %d", rec.UpID)
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
ri := &model.RecommendInfo{}
|
|||
|
ri.FromCard(card)
|
|||
|
ri.RecommendContent = *rec
|
|||
|
ri.TrackID = trackID
|
|||
|
ri.Fans = stat.Follower
|
|||
|
ri.TypeName = typeName(ri.Tid)
|
|||
|
ri.SecondTypeName = typeName(ri.SecondTid)
|
|||
|
|
|||
|
// zhangsusu: 拼粉丝数作为推荐理由(后来又下线了)
|
|||
|
// fs := followerString(stat.Follower)
|
|||
|
// if fs != "" {
|
|||
|
// parts := []string{}
|
|||
|
// if ri.RecReason != "" {
|
|||
|
// parts = append(parts, ri.RecReason)
|
|||
|
// }
|
|||
|
// parts = append(parts, fs)
|
|||
|
// ri.RecReason = strings.Join(parts, ",")
|
|||
|
// }
|
|||
|
|
|||
|
ris = append(ris, ri)
|
|||
|
}
|
|||
|
|
|||
|
return ris, nil
|
|||
|
}
|
|||
|
|
|||
|
func (s *Service) recommend(c context.Context, serviceArea string, arg *model.ArgRecommend) ([]*model.RecommendInfo, error) {
|
|||
|
resp, err := s.dao.Recommend(c, arg.Mid, serviceArea, arg.MainTids, arg.SubTids, arg.Device, arg.PageSize, arg.RemoteIP)
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
return s.collectionAsRecommendUserInfo(c, resp.Data, resp.TrackID, arg.RemoteIP)
|
|||
|
}
|
|||
|
|
|||
|
// func followerString(follower int64) string {
|
|||
|
// if follower <= 0 {
|
|||
|
// return ""
|
|||
|
// }
|
|||
|
// if follower < 10000 {
|
|||
|
// return fmt.Sprintf("%d粉丝", follower)
|
|||
|
// }
|
|||
|
// return fmt.Sprintf("%.1f万粉丝", float64(follower)/float64(10000))
|
|||
|
// }
|
|||
|
|
|||
|
// AchieveGet is
|
|||
|
func (s *Service) AchieveGet(c context.Context, arg *model.ArgAchieveGet) (*mrl.AchieveGetReply, error) {
|
|||
|
rpcArg := &mrl.ArgAchieveGet{
|
|||
|
Award: arg.Award,
|
|||
|
Mid: arg.Mid,
|
|||
|
}
|
|||
|
return s.relationRPC.AchieveGet(c, rpcArg)
|
|||
|
}
|
|||
|
|
|||
|
// Achieve is
|
|||
|
func (s *Service) Achieve(c context.Context, arg *model.ArgAchieve) (*model.AchieveReply, error) {
|
|||
|
rpcArg := &mrl.ArgAchieve{
|
|||
|
AwardToken: arg.AwardToken,
|
|||
|
}
|
|||
|
achieve, err := s.relationRPC.Achieve(c, rpcArg)
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
|
|||
|
reply := &model.AchieveReply{
|
|||
|
Achieve: *achieve,
|
|||
|
Metadata: make(map[string]interface{}),
|
|||
|
}
|
|||
|
|
|||
|
info, err := s.accountRPC.Info3(c, &acml.ArgMid{Mid: achieve.Mid})
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
|
|||
|
reply.Metadata["mid"] = info.Mid
|
|||
|
reply.Metadata["name"] = info.Name
|
|||
|
|
|||
|
return reply, nil
|
|||
|
}
|
|||
|
|
|||
|
// FollowerNotifySetting get new-follower-notification setting
|
|||
|
func (s *Service) FollowerNotifySetting(c context.Context, mid int64) (followerNotify *mrl.FollowerNotifySetting, err error) {
|
|||
|
arg := &mrl.ArgMid{
|
|||
|
Mid: mid,
|
|||
|
RealIP: metadata.String(c, metadata.RemoteIP),
|
|||
|
}
|
|||
|
return s.relationRPC.FollowerNotifySetting(c, arg)
|
|||
|
}
|
|||
|
|
|||
|
// EnableFollowerNotify enable new-follower-notification
|
|||
|
func (s *Service) EnableFollowerNotify(c context.Context, mid int64) (err error) {
|
|||
|
arg := &mrl.ArgMid{
|
|||
|
Mid: mid,
|
|||
|
RealIP: metadata.String(c, metadata.RemoteIP),
|
|||
|
}
|
|||
|
return s.relationRPC.EnableFollowerNotify(c, arg)
|
|||
|
}
|
|||
|
|
|||
|
// DisableFollowerNotify enable new-follower-notification
|
|||
|
func (s *Service) DisableFollowerNotify(c context.Context, mid int64) (err error) {
|
|||
|
arg := &mrl.ArgMid{
|
|||
|
Mid: mid,
|
|||
|
RealIP: metadata.String(c, metadata.RemoteIP),
|
|||
|
}
|
|||
|
return s.relationRPC.DisableFollowerNotify(c, arg)
|
|||
|
}
|
|||
|
|
|||
|
// SameFollowings is
|
|||
|
func (s *Service) SameFollowings(c context.Context, arg *model.ArgSameFollowing) (f []*model.Following, crc32v uint32, total int, err error) {
|
|||
|
sfArg := &mrl.ArgSameFollowing{Mid1: arg.VMid, Mid2: arg.Mid}
|
|||
|
fr, err := s.relationRPC.SameFollowings(c, sfArg)
|
|||
|
if err != nil {
|
|||
|
log.Error("s.SameFollowings(%+v) err(%v)", arg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
total = len(fr)
|
|||
|
if arg.Order == "asc" {
|
|||
|
// 直接倒序即可
|
|||
|
for i := len(fr)/2 - 1; i >= 0; i-- {
|
|||
|
opp := len(fr) - 1 - i
|
|||
|
fr[i], fr[opp] = fr[opp], fr[i]
|
|||
|
}
|
|||
|
}
|
|||
|
start, end := (arg.PN-1)*arg.PS, arg.PN*arg.PS
|
|||
|
switch {
|
|||
|
case start >= int64(len(fr)):
|
|||
|
fr = fr[:0]
|
|||
|
case end >= int64(len(fr)):
|
|||
|
fr = fr[start:]
|
|||
|
default:
|
|||
|
fr = fr[start:end]
|
|||
|
}
|
|||
|
if len(fr) == 0 {
|
|||
|
f = _emptyFollowings
|
|||
|
return
|
|||
|
}
|
|||
|
mids := make([]int64, 0, len(fr))
|
|||
|
for _, fi := range fr {
|
|||
|
mids = append(mids, fi.Mid)
|
|||
|
}
|
|||
|
temp := []byte(fmt.Sprintf("%s", fr))
|
|||
|
crc32v = crc32.Checksum(temp, crc32.IEEETable)
|
|||
|
if uint64(crc32v) == arg.ReVersion {
|
|||
|
err = ecode.NotModified
|
|||
|
return
|
|||
|
}
|
|||
|
accArg := &acml.ArgMids{Mids: mids}
|
|||
|
cards, err := s.accountRPC.Cards3(c, accArg)
|
|||
|
if err != nil {
|
|||
|
log.Error("s.accountRPC.Cards3(mid:%v) err(%v)", accArg, err)
|
|||
|
return
|
|||
|
}
|
|||
|
for _, fi := range fr {
|
|||
|
tmp := &model.Following{Following: fi}
|
|||
|
card, ok := cards[fi.Mid]
|
|||
|
if !ok {
|
|||
|
log.Warn("Failed to fetch card with mid: %d", fi.Mid)
|
|||
|
continue
|
|||
|
}
|
|||
|
tmp.Face = card.Face
|
|||
|
tmp.Uname = card.Name
|
|||
|
tmp.Sign = card.Sign
|
|||
|
of := card.Official
|
|||
|
if of.Role == 0 {
|
|||
|
tmp.OfficialVerify.Type = -1
|
|||
|
} else {
|
|||
|
if of.Role <= 2 {
|
|||
|
tmp.OfficialVerify.Type = 0
|
|||
|
} else {
|
|||
|
tmp.OfficialVerify.Type = 1
|
|||
|
}
|
|||
|
tmp.OfficialVerify.Desc = of.Title
|
|||
|
}
|
|||
|
tmp.Vip.Type = int(card.Vip.Type)
|
|||
|
tmp.Vip.VipStatus = int(card.Vip.Status)
|
|||
|
tmp.Vip.DueDate = card.Vip.DueDate
|
|||
|
f = append(f, tmp)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|