commit a7b00a0
Hubert Hirtz
·
2026-03-10 18:39:10 +0000 UTC
parent 89ba4ff
Check for CLIENTTAGDENY before sending @+typing ref: https://ircv3.net/specs/extensions/message-tags#rpl_isupport-tokens
1 files changed,
+29,
-2
+29,
-2
1@@ -160,6 +160,9 @@ type Session struct {
2 listMask bool
3 upload string
4
5+ clientTagListIsAllow bool // whether clientTagList is an allowlist (true) or a blocklist (false)
6+ clientTagList map[string]struct{}
7+
8 users map[string]*User // known users.
9 channels map[string]Channel // joined channels.
10 metadata map[string]Metadata // known target metadata.
11@@ -200,6 +203,7 @@ func NewSession(out chan<- Message, params SessionParams) *Session {
12 historyLimit: 100,
13 prefixSymbols: "@+",
14 prefixModes: "ov",
15+ clientTagList: map[string]struct{}{},
16 users: map[string]*User{},
17 channels: map[string]Channel{},
18 metadata: map[string]Metadata{},
19@@ -252,6 +256,11 @@ func (s *Session) HasCapability(capability string) bool {
20 return ok
21 }
22
23+func (s *Session) CanSendTag(clientTagWithoutThePlus string) bool {
24+ _, ok := s.clientTagList[clientTagWithoutThePlus]
25+ return ok == s.clientTagListIsAllow
26+}
27+
28 func (s *Session) IsBouncer() bool {
29 if s.HasCapability("soju.im/bouncer-networks") { // soju-compatible
30 return true
31@@ -522,7 +531,7 @@ func (s *Session) PrivMsg(target, content string) {
32 }
33
34 func (s *Session) Typing(target string) {
35- if !s.HasCapability("message-tags") {
36+ if !s.HasCapability("message-tags") || !s.CanSendTag("typing") {
37 return
38 }
39 targetCf := s.casemap(target)
40@@ -544,7 +553,7 @@ func (s *Session) Typing(target string) {
41 }
42
43 func (s *Session) TypingStop(target string) {
44- if !s.HasCapability("message-tags") {
45+ if !s.HasCapability("message-tags") || !s.CanSendTag("typing") {
46 return
47 }
48 targetCf := s.casemap(target)
49@@ -2225,6 +2234,24 @@ func (s *Session) updateFeatures(features []string) {
50 s.users[s.nickCf] = u
51 }
52 }
53+ case "CLIENTTAGDENY":
54+ clear(s.clientTagList)
55+ s.clientTagListIsAllow = strings.HasPrefix(value, "*")
56+ tags := strings.Split(value, ",")
57+ if s.clientTagListIsAllow {
58+ tags = tags[1:]
59+ }
60+ for _, tag := range tags {
61+ if s.clientTagListIsAllow {
62+ if !strings.HasPrefix(tag, "-") {
63+ continue
64+ }
65+ tag = tag[1:]
66+ } else if strings.HasPrefix(tag, "-") {
67+ continue
68+ }
69+ s.clientTagList[tag] = struct{}{}
70+ }
71 case "CHANMODES":
72 // We only care about the first four params
73 types := strings.SplitN(value, ",", 5)