You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
240 lines
6.1 KiB
240 lines
6.1 KiB
package service |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
"strconv" |
|
"time" |
|
|
|
"go-common/library/cache/redis" |
|
"go-common/library/log" |
|
|
|
farm "github.com/dgryski/go-farm" |
|
) |
|
|
|
const ( |
|
// aid_ip |
|
_anonymousePlayedKey = "nm:%d" |
|
// aid bvid |
|
_anonymouseBvIDKey = "nb:%d" |
|
// bvid's last played aid |
|
_bvIDLastPlayedKey = "bv:%d" |
|
// Mid last played key |
|
_midHashKey = "mid:%d" |
|
_buvidToDidKey = "%d:bdid" |
|
// 改短成6分钟 |
|
_hkeyExpire = 600 |
|
) |
|
|
|
func (s *Service) midKey(mid int64) (key string) { |
|
key = fmt.Sprintf(_midHashKey, mid%s.c.HashNum) |
|
return |
|
} |
|
|
|
func (s *Service) bvKey(bvID string) (key string) { |
|
num := int64(farm.Hash32([]byte(bvID))) |
|
key = fmt.Sprintf(_bvIDLastPlayedKey, num%s.c.HashNum) |
|
return |
|
} |
|
|
|
func (s *Service) buvidToDidKey(buvid string, aid int64) (key string) { |
|
num := int64(farm.Hash32([]byte(fmt.Sprintf("%s_%d", buvid, aid)))) |
|
key = fmt.Sprintf(_buvidToDidKey, num%s.c.HashNum) |
|
return |
|
} |
|
|
|
func (s *Service) anonymouseKey(aid, epID int64, ip string) (key string) { |
|
var str string |
|
if epID == 0 { |
|
str = strconv.Itoa(int(aid)) + ip |
|
} else { |
|
str = strconv.Itoa(int(aid)) + ip + strconv.Itoa(int(epID)) |
|
} |
|
num := int64(farm.Hash32([]byte(str))) |
|
key = fmt.Sprintf(_anonymousePlayedKey, num%s.c.HashNum) |
|
return |
|
} |
|
|
|
func (s *Service) anonymouseBvIDKey(aid int64, bvid string) (key string) { |
|
str := strconv.Itoa(int(aid)) + bvid |
|
num := int64(farm.Hash32([]byte(str))) |
|
key = fmt.Sprintf(_anonymouseBvIDKey, num%s.c.HashNum) |
|
return |
|
} |
|
|
|
// canCount 同一个IP一分钟,同一个bvid五分钟 |
|
func (s *Service) canCount(c context.Context, aid, epID int64, ip string, stime int64, bvid string) (can bool) { |
|
var ( |
|
err error |
|
lastPlayTime int64 |
|
bvLastPlayTime int64 |
|
hKey = s.anonymouseKey(aid, epID, ip) |
|
hbvKey = s.anonymouseBvIDKey(aid, bvid) |
|
conn = s.redis.Get(c) |
|
pTime = stime + s.c.CacheConf.NewAnonymousCacheTime |
|
now = time.Now().Unix() |
|
ipCan bool |
|
bvCan bool |
|
) |
|
var field = aid |
|
if epID > 0 { |
|
field = epID |
|
} |
|
defer conn.Close() |
|
if lastPlayTime, err = redis.Int64(conn.Do("HGET", hKey, field)); err != nil { |
|
if err == redis.ErrNil { |
|
if _, err = conn.Do("HSET", hKey, field, pTime); err != nil { |
|
log.Error("conn.Do(HSET, %s, %d, %d) error(%v)", hKey, field, pTime, err) |
|
return |
|
} |
|
ipCan = true |
|
} else { |
|
log.Error("conn.Do(HGET, %s, %d) error(%v)", hKey, field, err) |
|
return |
|
} |
|
} |
|
if bvLastPlayTime, err = redis.Int64(conn.Do("HGET", hbvKey, field)); err != nil { |
|
if err == redis.ErrNil { |
|
if _, err = conn.Do("HSET", hbvKey, field, pTime); err != nil { |
|
log.Error("conn.Do(HSET, %s, %d, %d)", hbvKey, field, pTime) |
|
return |
|
} |
|
bvCan = true |
|
} else { |
|
log.Error("conn.Do(HGET, %s, %d) error(%v)", hbvKey, field, err) |
|
return |
|
} |
|
} |
|
if ipCan && bvCan { |
|
can = true |
|
return |
|
} |
|
if now > lastPlayTime && now > bvLastPlayTime { |
|
if err = conn.Send("HSET", hKey, field, now+s.c.CacheConf.NewAnonymousCacheTime); err != nil { |
|
log.Error("conn.Send(HSET, %s, %s, %d) error(%v)", hKey, field, now+s.c.CacheConf.NewAnonymousCacheTime, err) |
|
return |
|
} |
|
if err = conn.Send("EXPIRE", hKey, _hkeyExpire); err != nil { |
|
log.Error("conn.Do(EXPIRE, %s, %d) error(%v)", hKey, _hkeyExpire, err) |
|
return |
|
} |
|
if err = conn.Send("HSET", hbvKey, field, now+s.c.CacheConf.NewAnonymousBvCacheTime); err != nil { |
|
log.Error("conn.Send(HSET, %s, %d, %d) error(%v)", hbvKey, field, now+s.c.CacheConf.NewAnonymousBvCacheTime, err) |
|
return |
|
} |
|
if err = conn.Send("EXPIRE", hbvKey, _hkeyExpire); err != nil { |
|
log.Error("conn.Do(EXPIRE, %s, %d) error(%v)", hbvKey, _hkeyExpire, err) |
|
return |
|
} |
|
if err = conn.Flush(); err != nil { |
|
log.Error("conn.Flush error(%v)") |
|
return |
|
} |
|
for i := 0; i < 4; i++ { |
|
if _, err = conn.Receive(); err != nil { |
|
log.Error("conn.Receive error(%v)", err) |
|
return |
|
} |
|
} |
|
can = true |
|
} |
|
return |
|
} |
|
|
|
func (s *Service) isReplay(c context.Context, mid, aid int64, bvID string, gapTime int64) (is bool) { |
|
var ( |
|
hKey string |
|
field string |
|
conn = s.redis.Get(c) |
|
value int64 |
|
err error |
|
now = time.Now().Unix() |
|
) |
|
defer conn.Close() |
|
if mid > 0 { |
|
hKey = s.midKey(mid) |
|
field = strconv.Itoa(int(mid)) |
|
} else { |
|
hKey = s.bvKey(bvID) |
|
field = bvID |
|
} |
|
// aid << 32 | ptime |
|
if value, err = redis.Int64(conn.Do("HGET", hKey, field)); err != nil { |
|
if err != redis.ErrNil { |
|
log.Error("conn.Do(HGET, %s, %s) error(%s)", hKey, field, err) |
|
return |
|
} |
|
err = nil |
|
} |
|
if value != 0 { |
|
rOid := value >> 32 |
|
rNow := value & 0xffffffff |
|
if rOid == aid && now-rNow < gapTime { |
|
is = true |
|
return |
|
} |
|
} |
|
value = aid<<32 | now |
|
if err = conn.Send("HSET", hKey, field, value); err != nil { |
|
log.Error("conn.Do(HSET, %s, %s, %s) error(%v)", hKey, field, value, err) |
|
return |
|
} |
|
if err = conn.Send("EXPIRE", hKey, _hkeyExpire); err != nil { |
|
log.Error("conn.Do(EXPIRE, %s, %d)", hKey, _hkeyExpire) |
|
return |
|
} |
|
if err = conn.Flush(); err != nil { |
|
log.Error("conn.Flush error(%v)") |
|
return |
|
} |
|
for i := 0; i < 2; i++ { |
|
if _, err = conn.Receive(); err != nil { |
|
log.Error("conn.Receive error(%v)", err) |
|
return |
|
} |
|
} |
|
return |
|
} |
|
|
|
func (s *Service) getRealDid(c context.Context, buvid string, aid int64) (did string, err error) { |
|
var ( |
|
conn = s.redis.Get(c) |
|
key = s.buvidToDidKey(buvid, aid) |
|
) |
|
defer conn.Close() |
|
if did, err = redis.String(conn.Do("HGET", key, buvid)); err != nil { |
|
if err != redis.ErrNil { |
|
log.Error("redis.String(conn.Do(HGET, %s, %s)) error(%v)", key, buvid, err) |
|
return |
|
} |
|
err = nil |
|
} |
|
return |
|
} |
|
|
|
func (s *Service) setRealDid(c context.Context, buvid string, aid int64, did string) (err error) { |
|
var ( |
|
conn = s.redis.Get(c) |
|
key = s.buvidToDidKey(buvid, aid) |
|
) |
|
defer conn.Close() |
|
if err = conn.Send("HSET", key, buvid, did); err != nil { |
|
log.Error("conn.Do(HSET, %s, %s, %s) error(%v)", key, buvid, did, err) |
|
return |
|
} |
|
if err = conn.Send("EXPIRE", key, _hkeyExpire); err != nil { |
|
log.Error("conn.Send(EXPIRE, %s, %d) error(%v)", key, _hkeyExpire, err) |
|
return |
|
} |
|
if err = conn.Flush(); err != nil { |
|
log.Error("conn.Flush error(%v)", err) |
|
return |
|
} |
|
for i := 0; i < 2; i++ { |
|
if _, err = conn.Receive(); err != nil { |
|
log.Error("conn.Receive error(%v)", err) |
|
return |
|
} |
|
} |
|
return |
|
}
|
|
|