391 lines
10 KiB
Go
391 lines
10 KiB
Go
|
package account
|
|||
|
|
|||
|
import (
|
|||
|
"context"
|
|||
|
"go-common/app/interface/main/creative/conf"
|
|||
|
"go-common/app/interface/main/creative/model/appeal"
|
|||
|
accapi "go-common/app/service/main/account/api"
|
|||
|
relaMdl "go-common/app/service/main/relation/model"
|
|||
|
relation "go-common/app/service/main/relation/rpc/client"
|
|||
|
"go-common/library/cache/memcache"
|
|||
|
"go-common/library/ecode"
|
|||
|
"go-common/library/log"
|
|||
|
httpx "go-common/library/net/http/blademaster"
|
|||
|
"go-common/library/sync/errgroup"
|
|||
|
"net/http"
|
|||
|
"net/url"
|
|||
|
"time"
|
|||
|
)
|
|||
|
|
|||
|
const (
|
|||
|
_pass = "/web/site/userInfo"
|
|||
|
_richRelation = "/x/account/relation/rich"
|
|||
|
_relation = "/x/internal/relation"
|
|||
|
)
|
|||
|
|
|||
|
// Dao is account dao.
|
|||
|
type Dao struct {
|
|||
|
c *conf.Config
|
|||
|
// rpc
|
|||
|
acc accapi.AccountClient
|
|||
|
rela *relation.Service
|
|||
|
// http client
|
|||
|
client *httpx.Client
|
|||
|
fastClient *httpx.Client
|
|||
|
mc *memcache.Pool
|
|||
|
mcExpire int32
|
|||
|
// user
|
|||
|
passURI string
|
|||
|
relationURI string
|
|||
|
richRelationURI string
|
|||
|
picUpInfoURL string
|
|||
|
blinkUpInfoURL string
|
|||
|
upInfoURL string
|
|||
|
}
|
|||
|
|
|||
|
// New new a dao.
|
|||
|
func New(c *conf.Config) (d *Dao) {
|
|||
|
d = &Dao{
|
|||
|
c: c,
|
|||
|
rela: relation.New(c.RelationRPC),
|
|||
|
// http client
|
|||
|
client: httpx.NewClient(c.HTTPClient.Normal),
|
|||
|
fastClient: httpx.NewClient(c.HTTPClient.Fast),
|
|||
|
passURI: c.Host.Passport + _pass,
|
|||
|
relationURI: c.Host.API + _relation,
|
|||
|
richRelationURI: c.Host.API + _richRelation,
|
|||
|
picUpInfoURL: c.Host.Live + _picUpInfoURL,
|
|||
|
blinkUpInfoURL: c.Host.Live + _blinkUpInfoURL,
|
|||
|
upInfoURL: c.Host.API + _upInfoURL,
|
|||
|
mc: memcache.NewPool(c.Memcache.Archive.Config),
|
|||
|
mcExpire: int32(time.Duration(c.Memcache.Archive.TplExpire) / time.Second),
|
|||
|
}
|
|||
|
var err error
|
|||
|
if d.acc, err = accapi.NewClient(c.AccClient); err != nil {
|
|||
|
panic(err)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Profile get account.
|
|||
|
func (d *Dao) Profile(c context.Context, mid int64, ip string) (res *accapi.Profile, err error) {
|
|||
|
var (
|
|||
|
arg = &accapi.MidReq{
|
|||
|
Mid: mid,
|
|||
|
}
|
|||
|
rpcRes *accapi.ProfileReply
|
|||
|
)
|
|||
|
if rpcRes, err = d.acc.Profile3(c, arg); err != nil {
|
|||
|
log.Error("d.acc.Profile3 error(%v)", err)
|
|||
|
err = ecode.CreativeAccServiceErr
|
|||
|
}
|
|||
|
if rpcRes != nil {
|
|||
|
res = rpcRes.Profile
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// ProfileWithStat get account.
|
|||
|
func (d *Dao) ProfileWithStat(c context.Context, mid int64) (res *accapi.ProfileStatReply, err error) {
|
|||
|
var (
|
|||
|
arg = &accapi.MidReq{
|
|||
|
Mid: mid,
|
|||
|
}
|
|||
|
)
|
|||
|
if res, err = d.acc.ProfileWithStat3(c, arg); err != nil {
|
|||
|
log.Error("d.acc.ProfileWithStat3() error(%v)", err)
|
|||
|
err = ecode.CreativeAccServiceErr
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Card get account.
|
|||
|
func (d *Dao) Card(c context.Context, mid int64, ip string) (res *accapi.Card, err error) {
|
|||
|
var (
|
|||
|
rpcRes *accapi.CardReply
|
|||
|
arg = &accapi.MidReq{
|
|||
|
Mid: mid,
|
|||
|
}
|
|||
|
)
|
|||
|
if rpcRes, err = d.acc.Card3(c, arg); err != nil {
|
|||
|
log.Error("d.acc.Card3() error(%v)", err)
|
|||
|
err = ecode.CreativeAccServiceErr
|
|||
|
}
|
|||
|
if rpcRes != nil {
|
|||
|
res = rpcRes.Card
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Cards get cards from rpc
|
|||
|
func (d *Dao) Cards(c context.Context, mids []int64, ip string) (cards map[int64]*accapi.Card, err error) {
|
|||
|
if len(mids) == 0 {
|
|||
|
return
|
|||
|
}
|
|||
|
arg := &accapi.MidsReq{
|
|||
|
Mids: mids,
|
|||
|
}
|
|||
|
var reply *accapi.CardsReply
|
|||
|
if reply, err = d.acc.Cards3(c, arg); err != nil {
|
|||
|
log.Error("d.acc.Cards3 error(%v) | mids(%v) ip(%s) arg(%v)", err, mids, ip, arg)
|
|||
|
err = ecode.CreativeAccServiceErr
|
|||
|
return
|
|||
|
}
|
|||
|
cards = reply.Cards
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// PhoneEmail get user email & phone
|
|||
|
func (d *Dao) PhoneEmail(c context.Context, ck, ip string) (ct *appeal.Contact, err error) {
|
|||
|
params := url.Values{}
|
|||
|
params.Set("Cookie", ck)
|
|||
|
// init req set cookie
|
|||
|
req, err := http.NewRequest("GET", d.passURI, nil)
|
|||
|
if err != nil {
|
|||
|
log.Error("passport url(%s) error(%v)", d.passURI, err)
|
|||
|
return
|
|||
|
}
|
|||
|
req.Header.Set("Cookie", ck)
|
|||
|
req.Header.Set("X-BACKEND-BILI-REAL-IP", ip)
|
|||
|
var res struct {
|
|||
|
Code int `json:"code"`
|
|||
|
Data *appeal.Contact `json:"data"`
|
|||
|
}
|
|||
|
if err = d.client.Do(c, req, &res); err != nil {
|
|||
|
log.Error("passport url(%s) response(%+v) error(%v)", d.passURI+"?"+params.Encode(), res, err)
|
|||
|
err = ecode.CreativeAccServiceErr
|
|||
|
return
|
|||
|
}
|
|||
|
if res.Code != 0 {
|
|||
|
log.Error("passport url(%s) res(%v)", d.passURI, res)
|
|||
|
err = ecode.CreativeAccServiceErr
|
|||
|
return
|
|||
|
}
|
|||
|
ct = res.Data
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// RichRelation get multi user relations
|
|||
|
func (d *Dao) RichRelation(c context.Context, owner int64, mids []int64, ip string) (richRel map[int64]int32, err error) {
|
|||
|
var rpcRes *accapi.RichRelationsReply
|
|||
|
if rpcRes, err = d.acc.RichRelations3(c, &accapi.RichRelationReq{Owner: owner, Mids: mids}); err != nil {
|
|||
|
log.Error("d.acc.RichRelations3(%d, %v) error(%v)", owner, mids, err)
|
|||
|
err = ecode.CreativeAccServiceErr
|
|||
|
}
|
|||
|
if rpcRes != nil {
|
|||
|
richRel = rpcRes.RichRelations
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Followers get users only follower relation which attr eq 2 with errgroup
|
|||
|
func (d *Dao) Followers(c context.Context, owner int64, mids []int64, ip string) (relations map[int64]int, err error) {
|
|||
|
relations = make(map[int64]int, len(mids))
|
|||
|
type midRel struct {
|
|||
|
mid int64
|
|||
|
rel int
|
|||
|
}
|
|||
|
rechan := make(chan midRel, len(mids)) // avoid concurrent write map
|
|||
|
g, ctx := errgroup.WithContext(c)
|
|||
|
for _, mid := range mids {
|
|||
|
var mid2 = mid // for closure, copy to avoid same mid
|
|||
|
g.Go(func() error {
|
|||
|
rl, e := d.acc.Relation3(ctx, &accapi.RelationReq{Mid: mid2, Owner: owner})
|
|||
|
if e != nil || rl == nil || !rl.Following {
|
|||
|
if e != nil {
|
|||
|
log.Error("d.acc.Relation3(mid:%d,owner:%d,relation:%v) error(%v)", mid2, owner, rl, e)
|
|||
|
}
|
|||
|
rechan <- midRel{mid2, 1}
|
|||
|
} else {
|
|||
|
rechan <- midRel{mid2, 2}
|
|||
|
}
|
|||
|
return nil
|
|||
|
})
|
|||
|
}
|
|||
|
g.Wait()
|
|||
|
for i := 0; i < len(mids); i++ {
|
|||
|
wc := <-rechan
|
|||
|
relations[wc.mid] = wc.rel
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Infos get user info by mids.
|
|||
|
func (d *Dao) Infos(c context.Context, mids []int64, ip string) (res map[int64]*accapi.Info, err error) {
|
|||
|
res = make(map[int64]*accapi.Info)
|
|||
|
if len(mids) == 0 {
|
|||
|
return
|
|||
|
}
|
|||
|
var arg = &accapi.MidsReq{
|
|||
|
Mids: mids,
|
|||
|
}
|
|||
|
var rpcRes *accapi.InfosReply
|
|||
|
if rpcRes, err = d.acc.Infos3(c, arg); err != nil {
|
|||
|
log.Error("d.acc.Infos3() error(%v)|ip(%s)", err, ip)
|
|||
|
err = ecode.CreativeAccServiceErr
|
|||
|
}
|
|||
|
if rpcRes != nil {
|
|||
|
res = rpcRes.Infos
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// IdentifyInfo 获取用户实名认证状态
|
|||
|
// tel_status int 0未绑定,1已绑定有效手机号 2绑定虚拟号段170/171
|
|||
|
// identification int 身份证绑定状态,0:未绑定 1:已绑定
|
|||
|
func (d *Dao) IdentifyInfo(c context.Context, mid int64, phoneOnly int8, ip string) (ret int, err error) {
|
|||
|
var (
|
|||
|
rpcRes *accapi.ProfileReply
|
|||
|
arg = &accapi.MidReq{
|
|||
|
Mid: mid,
|
|||
|
}
|
|||
|
mf *accapi.Profile
|
|||
|
)
|
|||
|
if rpcRes, err = d.acc.Profile3(c, arg); err != nil {
|
|||
|
log.Error("d.acc.Profile3 error(%v) | mid(%d) ip(%s) arg(%v)", err, mid, ip, arg)
|
|||
|
err = ecode.CreativeAccServiceErr
|
|||
|
return
|
|||
|
}
|
|||
|
if rpcRes != nil {
|
|||
|
mf = rpcRes.Profile
|
|||
|
}
|
|||
|
//switch for FrontEnd return json format
|
|||
|
ret = d.switchPhoneRet(int(mf.TelStatus))
|
|||
|
if phoneOnly == 1 {
|
|||
|
return
|
|||
|
}
|
|||
|
if mf.TelStatus == 1 || mf.Identification == 1 {
|
|||
|
return 0, err
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// MidByName 获取mid
|
|||
|
func (d *Dao) MidByName(c context.Context, name string) (mid int64, err error) {
|
|||
|
var (
|
|||
|
rpcRes *accapi.InfosReply
|
|||
|
arg = &accapi.NamesReq{
|
|||
|
Names: []string{name},
|
|||
|
}
|
|||
|
infos map[int64]*accapi.Info
|
|||
|
)
|
|||
|
if rpcRes, err = d.acc.InfosByName3(c, arg); err != nil {
|
|||
|
log.Error("d.acc.InfosByName3 error(%v)", err)
|
|||
|
err = ecode.CreativeAccServiceErr
|
|||
|
return
|
|||
|
}
|
|||
|
if rpcRes != nil {
|
|||
|
infos = rpcRes.Infos
|
|||
|
}
|
|||
|
for _, v := range infos {
|
|||
|
if v != nil && v.Name == name {
|
|||
|
return v.Mid, nil
|
|||
|
}
|
|||
|
}
|
|||
|
err = ecode.AccountInexistence
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 0: "已实名认证",
|
|||
|
// 1: "根据国家实名制认证的相关要求,您需要换绑一个非170/171的手机号,才能继续进行操作。",
|
|||
|
// 2: "根据国家实名制认证的相关要求,您需要绑定手机号,才能继续进行操作。",
|
|||
|
func (d *Dao) switchPhoneRet(newV int) (oldV int) {
|
|||
|
switch newV {
|
|||
|
case 0:
|
|||
|
oldV = 2
|
|||
|
case 1:
|
|||
|
oldV = 0
|
|||
|
case 2:
|
|||
|
oldV = 1
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// CheckIdentify fn
|
|||
|
func (d *Dao) CheckIdentify(identify int) (err error) {
|
|||
|
switch identify {
|
|||
|
case 0:
|
|||
|
err = nil
|
|||
|
case 1:
|
|||
|
err = ecode.UserCheckInvalidPhone
|
|||
|
case 2:
|
|||
|
err = ecode.UserCheckNoPhone
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// RelationFollowers get all relation state.
|
|||
|
func (d *Dao) RelationFollowers(c context.Context, mid int64, ip string) (res map[int64]int32, err error) {
|
|||
|
var fls []*relaMdl.Following
|
|||
|
if fls, err = d.rela.Followers(c, &relaMdl.ArgMid{Mid: mid, RealIP: ip}); err != nil {
|
|||
|
log.Error("d.rela.Followers mid(%d)|ip(%s)|error(%v)", mid, ip, err)
|
|||
|
return
|
|||
|
}
|
|||
|
if len(fls) == 0 {
|
|||
|
log.Info("d.rela.Followers mid(%d)|ip(%s)", mid, ip)
|
|||
|
return
|
|||
|
}
|
|||
|
res = make(map[int64]int32, len(fls))
|
|||
|
for _, v := range fls {
|
|||
|
res[v.Mid] = int32(v.Attribute)
|
|||
|
}
|
|||
|
log.Info("d.rela.Followers mid(%d)|res(%+v)|ip(%s)", mid, res, ip)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Relations get all relation state.
|
|||
|
func (d *Dao) Relations(c context.Context, mid int64, fids []int64, ip string) (res map[int64]int, err error) {
|
|||
|
var rls map[int64]*relaMdl.Following
|
|||
|
if rls, err = d.rela.Relations(c, &relaMdl.ArgRelations{Mid: mid, Fids: fids, RealIP: ip}); err != nil {
|
|||
|
log.Error("d.rela.Relations mid(%d)|ip(%s)|error(%v)", mid, ip, err)
|
|||
|
err = ecode.CreativeAccServiceErr
|
|||
|
return
|
|||
|
}
|
|||
|
if len(rls) == 0 {
|
|||
|
log.Info("d.rela.Relations mid(%d)|ip(%s)", mid, ip)
|
|||
|
return
|
|||
|
}
|
|||
|
res = make(map[int64]int, len(rls))
|
|||
|
for _, v := range rls {
|
|||
|
res[v.Mid] = int(v.Attribute)
|
|||
|
}
|
|||
|
log.Info("d.rela.Relations mid(%d)|res(%+v)|rls(%+v)|ip(%s)", mid, res, rls, ip)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Relations2
|
|||
|
func (d *Dao) Relations2(c context.Context, mid int64, fids []int64, ip string) (res map[int64]int, err error) {
|
|||
|
if res, err = d.Relations(c, mid, fids, ip); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
for k, v := range res {
|
|||
|
if v == 2 || v == 6 { //2表示我关注他,6表示双向关注,为了兼容客户端统一吐出6作为已关注状态.
|
|||
|
res[k] = 6
|
|||
|
} else {
|
|||
|
delete(res, k)
|
|||
|
}
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// ShouldFollow fn
|
|||
|
func (d *Dao) ShouldFollow(c context.Context, mid int64, fids []int64, ip string) (shouldMids []int64, err error) {
|
|||
|
var rls map[int64]*relaMdl.Following
|
|||
|
if rls, err = d.rela.Relations(c, &relaMdl.ArgRelations{Mid: mid, Fids: fids, RealIP: ip}); err != nil {
|
|||
|
log.Error("d.rela.Relations mid(%d)|fids(%+v)|ip(%s)|error(%v)", mid, fids, ip, err)
|
|||
|
return
|
|||
|
}
|
|||
|
if len(rls) == 0 {
|
|||
|
shouldMids = fids
|
|||
|
return
|
|||
|
}
|
|||
|
shouldMids = make([]int64, 0)
|
|||
|
for _, v := range rls {
|
|||
|
if v.Attribute == 0 {
|
|||
|
shouldMids = append(shouldMids, v.Mid)
|
|||
|
}
|
|||
|
}
|
|||
|
log.Info("d.rela.Relations mid(%d)|shouldMids(%+v)|ip(%s)", mid, shouldMids, ip)
|
|||
|
return
|
|||
|
}
|