diff options
author | delthas <delthas@dille.cc> | 2021-07-12 11:43:22 +0200 |
---|---|---|
committer | Hubert Hirtz <hubert@hirtz.pm> | 2021-07-13 13:40:57 +0200 |
commit | 01c27150b773b578a24096caf5fa618ae3b19aa6 (patch) | |
tree | 58da8b4371b3c4e528c7e338d73d022a383a4f09 | |
parent | Sort channel members by name (diff) |
Ratelimit +typing and send +typing=done once only
-rw-r--r-- | go.mod | 1 | ||||
-rw-r--r-- | go.sum | 2 | ||||
-rw-r--r-- | irc/session.go | 37 | ||||
-rw-r--r-- | irc/typing.go | 8 |
4 files changed, 43 insertions, 5 deletions
@@ -6,5 +6,6 @@ require ( github.com/gdamore/tcell/v2 v2.3.11 github.com/mattn/go-runewidth v0.0.10 golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf + golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 gopkg.in/yaml.v2 v2.3.0 ) @@ -14,6 +14,8 @@ golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlp golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 h1:Vv0JUPWTyeqUq42B2WJ1FeIDjjvGKoA2Ss+Ts0lAVbs= +golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= diff --git a/irc/session.go b/irc/session.go index dabec03..376015f 100644 --- a/irc/session.go +++ b/irc/session.go @@ -11,6 +11,8 @@ import ( "time" "unicode" "unicode/utf8" + + "golang.org/x/time/rate" ) type SASLClient interface { @@ -102,8 +104,8 @@ type Session struct { out chan<- Message closed bool registered bool - typings *Typings // incoming typing notifications. - typingStamps map[string]time.Time // user typing instants. + typings *Typings // incoming typing notifications. + typingStamps map[string]typingStamp // user typing instants. nick string nickCf string // casemapped nickname. @@ -134,7 +136,7 @@ func NewSession(out chan<- Message, params SessionParams) *Session { s := &Session{ out: out, typings: NewTypings(), - typingStamps: map[string]time.Time{}, + typingStamps: map[string]typingStamp{}, nick: params.Nickname, nickCf: CasemapASCII(params.Nickname), user: params.Username, @@ -342,10 +344,19 @@ func (s *Session) Typing(target string) { } targetCf := s.casemap(target) now := time.Now() - if t, ok := s.typingStamps[targetCf]; ok && now.Sub(t).Seconds() < 3.0 { + t, ok := s.typingStamps[targetCf] + if ok && ((t.Type == TypingActive && now.Sub(t.Last).Seconds() < 3.0) || !t.Limit.Allow()) { return } - s.typingStamps[targetCf] = now + if !ok { + t.Limit = rate.NewLimiter(rate.Limit(1.0/3.0), 5) + t.Limit.Reserve() // will always be OK + } + s.typingStamps[targetCf] = typingStamp{ + Last: now, + Type: TypingActive, + Limit: t.Limit, + } s.out <- NewMessage("TAGMSG", target).WithTag("+typing", "active") } @@ -353,6 +364,22 @@ func (s *Session) TypingStop(target string) { if !s.HasCapability("message-tags") { return } + targetCf := s.casemap(target) + now := time.Now() + t, ok := s.typingStamps[targetCf] + if ok && (t.Type == TypingDone || !t.Limit.Allow()) { + // don't send a +typing=done again if the last typing we sent was a +typing=done + return + } + if !ok { + t.Limit = rate.NewLimiter(rate.Limit(1), 5) + t.Limit.Reserve() // will always be OK + } + s.typingStamps[targetCf] = typingStamp{ + Last: now, + Type: TypingDone, + Limit: t.Limit, + } s.out <- NewMessage("TAGMSG", target).WithTag("+typing", "done") } diff --git a/irc/typing.go b/irc/typing.go index 5f028e4..5a3073c 100644 --- a/irc/typing.go +++ b/irc/typing.go @@ -3,6 +3,8 @@ package irc import ( "sync" "time" + + "golang.org/x/time/rate" ) // Typing is an event of Name actively typing in Target. @@ -86,3 +88,9 @@ func (ts *Typings) List(target string) []string { } return res } + +type typingStamp struct { + Last time.Time + Type int + Limit *rate.Limiter +} |