summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordelthas <delthas@dille.cc>2021-07-12 11:43:22 +0200
committerHubert Hirtz <hubert@hirtz.pm>2021-07-13 13:40:57 +0200
commit01c27150b773b578a24096caf5fa618ae3b19aa6 (patch)
tree58da8b4371b3c4e528c7e338d73d022a383a4f09
parentSort channel members by name (diff)
Ratelimit +typing and send +typing=done once only
Fixes: #8 Fixes: #41
-rw-r--r--go.mod1
-rw-r--r--go.sum2
-rw-r--r--irc/session.go37
-rw-r--r--irc/typing.go8
4 files changed, 43 insertions, 5 deletions
diff --git a/go.mod b/go.mod
index 6fa2d6d..88f4550 100644
--- a/go.mod
+++ b/go.mod
@@ -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
)
diff --git a/go.sum b/go.sum
index a7c2983..c64f2e8 100644
--- a/go.sum
+++ b/go.sum
@@ -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
+}