diff --git a/client/decoders.go b/client/decoders.go index 9c0a3131..2b51c0f5 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -13,7 +13,6 @@ import ( "github.com/Mrs4s/MiraiGo/client/pb/structmsg" "github.com/Mrs4s/MiraiGo/utils" "github.com/golang/protobuf/proto" - "math" "sync" "sync/atomic" "time" @@ -229,12 +228,17 @@ func decodeMessageSvcPacket(c *QQClient, _ uint16, payload []byte) (interface{}, if message.Body.RichText == nil || message.Body.RichText.Elems == nil { continue } - if c.lastMessageSeq >= message.Head.MsgSeq { - if math.Abs(float64(c.lastMessageSeq-message.Head.MsgSeq)) < 1000 { - continue - } + friend := c.FindFriend(message.Head.FromUin) + if friend == nil { + return nil, nil } - c.lastMessageSeq = message.Head.MsgSeq + if friend.msgSeqList == nil { + friend.msgSeqList = utils.NewTTList(60) + } + if friend.msgSeqList.Any(func(i interface{}) bool { return i.(int32) == message.Head.MsgSeq }) { + continue + } + friend.msgSeqList.Add(message.Head.MsgSeq) c.dispatchFriendMessage(c.parsePrivateMessage(message)) case 187: _, pkt := c.buildSystemMsgNewFriendPacket() diff --git a/client/entities.go b/client/entities.go index 2bd3dfdd..cafffec1 100644 --- a/client/entities.go +++ b/client/entities.go @@ -2,6 +2,7 @@ package client import ( "errors" + "github.com/Mrs4s/MiraiGo/utils" "strings" "sync" ) @@ -35,6 +36,8 @@ type ( Nickname string Remark string FaceId int16 + + msgSeqList *utils.TTList } FriendListResponse struct { diff --git a/utils/ttlmap.go b/utils/ttlmap.go new file mode 100644 index 00000000..4248e900 --- /dev/null +++ b/utils/ttlmap.go @@ -0,0 +1,60 @@ +package utils + +import ( + "sync" + "time" +) + +type TTList struct { + list []*item + lock *sync.Mutex +} + +type item struct { + i interface{} + lastAccess int64 +} + +func NewTTList(ttl int64) *TTList { + l := &TTList{ + lock: new(sync.Mutex), + } + go func() { + for now := range time.Tick(time.Second * 5) { + l.lock.Lock() + pos := 0 + for _, i := range l.list { + if now.Unix()-i.lastAccess > ttl { + l.list = append(l.list[:pos], l.list[pos+1:]...) + if pos > 0 { + pos++ + } + } + pos++ + } + l.lock.Unlock() + } + }() + return l +} + +func (l *TTList) Add(i interface{}) { + l.lock.Lock() + l.lock.Unlock() + l.list = append(l.list, &item{ + i: i, + lastAccess: time.Now().Unix(), + }) +} + +func (l *TTList) Any(filter func(i interface{}) bool) bool { + l.lock.Lock() + l.lock.Unlock() + for _, it := range l.list { + if filter(it.i) { + it.lastAccess = time.Now().Unix() + return true + } + } + return false +}