123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- package dao
- import (
- "context"
- "crypto/md5"
- "fmt"
- "strconv"
- "time"
- "go-common/library/cache/redis"
- "go-common/library/ecode"
- "go-common/library/log"
- )
- // LimitCheckInfo 频率限制检查参数
- type LimitCheckInfo struct {
- UID int64
- RoomID int64
- Msg string
- MsgType int64
- Dao *Dao
- Conf *LimitConf
- }
- const (
- _MaxGiftMsgNum = "r:m:stormmsgcount:"
- _MAXMsgNum = "r:m:rmx:"
- )
- // LimitPerSec 每秒发言限制
- func (l *LimitCheckInfo) LimitPerSec(ctx context.Context) error {
- key := fmt.Sprintf("%d.%d", l.UID, time.Now().Unix())
- var conn = l.Dao.redis.Get(ctx)
- defer conn.Close()
- ret, err := conn.Do("SET", key, 1, "EX", 1, "NX")
- if err != nil {
- log.Error("limitPerSec:conn.Do(SET EX NX) %s %d %v", key, 1, err)
- return nil
- }
- if ret != nil {
- return nil
- }
- return ecode.Error(0, "msg in 1s")
- }
- //LimitSameMsg 同一个用户同一房间5s 只能发送一条相同弹幕
- func (l *LimitCheckInfo) LimitSameMsg(ctx context.Context) error {
- key := fmt.Sprintf("%d.%s", l.RoomID, md5.Sum([]byte(strconv.FormatInt(l.UID, 10)+l.Msg)))
- var conn = l.Dao.redis.Get(ctx)
- defer conn.Close()
- ret, err := conn.Do("SET", key, 1, "EX", 5, "NX")
- if err != nil {
- log.Error("DM LimitSameMsg conn.Do(SET, %s, 1, EX, 5, NX) error(%v)", key, err)
- return nil
- }
- if ret != nil {
- return nil
- }
- return ecode.Error(0, "msg repeat")
- }
- //LimitRoomPerSecond 单房间每秒只能发送制定条数弹幕
- func (l *LimitCheckInfo) LimitRoomPerSecond(ctx context.Context) error {
- maxNum := l.Conf.DmNum
- percent := l.Conf.DMPercent
- danNum := maxNum * percent / 100.0
- giftNum := maxNum - danNum
- msgKey := fmt.Sprintf("%s.%d.%d", _MAXMsgNum, l.RoomID, time.Now().Unix())
- giftKey := fmt.Sprintf("%s.%d.%d", _MaxGiftMsgNum, l.RoomID, time.Now().Unix())
- var conn = l.Dao.redis.Get(ctx)
- defer conn.Close()
- if l.MsgType != 0 {
- //礼物弹幕
- if count, err := redis.Int64(conn.Do("INCRBY", giftKey, 1)); err != nil {
- log.Error("DMRateLimit: LimitRoomPerSecond INCRBY err: %v", err)
- } else {
- if count > giftNum {
- return ecode.Error(0, "max limit")
- }
- }
- if _, err := conn.Do("EXPIRE", giftKey, 2); err != nil {
- log.Error("DMRateLimit: LimitRoomPerSecond EXPIRE err: %v", err)
- }
- return nil
- }
- //普通弹幕
- var max = maxNum
- if exit, err := redis.Bool(conn.Do("EXISTS", giftKey)); err != nil {
- log.Error("DMRateLimit: LimitRoomPerSecond EXISTS gift err: %v", err)
- } else {
- if exit {
- max = danNum
- } else {
- max = maxNum
- }
- }
- if count, err := redis.Int64(conn.Do("INCRBY", msgKey, 1)); err != nil {
- log.Error("DMRateLimit: LimitRoomPerSecond INCR err: %v", err)
- } else {
- if count > max {
- return ecode.Error(0, "max limit")
- }
- }
- if _, err := conn.Do("EXPIRE", msgKey, 2); err != nil {
- log.Error("DMRateLimit: LimitRoomPerSecond EXPIRE err: %v", err)
- }
- return nil
- }
|