123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- 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
- }
|