Skip to content

Commit 0cf66d7

Browse files
tidy up a bit
1 parent db4b23b commit 0cf66d7

File tree

10 files changed

+104
-67
lines changed

10 files changed

+104
-67
lines changed

gencapdefs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@
238238
standard="Soju/Goguma vendor",
239239
),
240240
CapDef(
241-
identifier="MetadataTwoJudgementDay",
241+
identifier="Metadata",
242242
name="draft/metadata-2",
243243
url="https://ircv3.net/specs/extensions/metadata",
244244
standard="draft IRCv3",

irc/caps/defs.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ const (
6565
// https://github.com/progval/ircv3-specifications/blob/redaction/extensions/message-redaction.md
6666
MessageRedaction Capability = iota
6767

68-
// MetadataTwoJudgementDay is the draft IRCv3 capability named "draft/metadata-2":
68+
// Metadata is the draft IRCv3 capability named "draft/metadata-2":
6969
// https://ircv3.net/specs/extensions/metadata
70-
MetadataTwoJudgementDay Capability = iota
70+
Metadata Capability = iota
7171

7272
// Multiline is the proposed IRCv3 capability named "draft/multiline":
7373
// https://github.com/ircv3/ircv3-specifications/pull/398

irc/channel.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ type Channel struct {
5555
dirtyBits uint
5656
settings ChannelSettings
5757
uuid utils.UUID
58-
metadata MetadataStore
58+
metadata map[string]string
5959
// these caches are paired to allow iteration over channel members without holding the lock
6060
membersCache []*Client
6161
memberDataCache []*memberData
@@ -895,6 +895,10 @@ func (channel *Channel) Join(client *Client, key string, isSajoin bool, rb *Resp
895895
rb.Add(nil, client.server.name, "MARKREAD", chname, client.GetReadMarker(chcfname))
896896
}
897897

898+
if rb.session.capabilities.Has(caps.Metadata) {
899+
syncChannelMetadata(client.server, rb, channel)
900+
}
901+
898902
if rb.session.client == client {
899903
// don't send topic and names for a SAJOIN of a different client
900904
channel.SendTopic(client, rb, false)

irc/channelreg.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ type RegisteredChannel struct {
6464
// Settings are the chanserv-modifiable settings
6565
Settings ChannelSettings
6666
// Metadata set using the METADATA command
67-
Metadata MetadataStore
67+
Metadata map[string]string
6868
}
6969

7070
func (r *RegisteredChannel) Serialize() ([]byte, error) {

irc/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ type Client struct {
131131
clearablePushMessages map[string]time.Time
132132
pushSubscriptionsExist atomic.Uint32 // this is a cache on len(pushSubscriptions) != 0
133133
pushQueue pushQueue
134-
metadata MetadataStore
134+
metadata map[string]string
135135
}
136136

137137
type saslStatus struct {
@@ -216,7 +216,7 @@ type Session struct {
216216

217217
webPushEndpoint string // goroutine-local: web push endpoint registered by the current session
218218

219-
metadataSubscriptions []string
219+
metadataSubscriptions utils.HashSet[string]
220220
}
221221

222222
// MultilineBatch tracks the state of a client-to-server multiline batch.

irc/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,7 +1646,7 @@ func LoadConfig(filename string) (config *Config, err error) {
16461646
}
16471647

16481648
if !config.Metadata.Enabled {
1649-
config.Server.supportedCaps.Disable(caps.MetadataTwoJudgementDay)
1649+
config.Server.supportedCaps.Disable(caps.Metadata)
16501650
} else {
16511651
var metadataValues []string
16521652
if config.Metadata.MaxSubs >= 0 {
@@ -1659,7 +1659,7 @@ func LoadConfig(filename string) (config *Config, err error) {
16591659
metadataValues = append(metadataValues, fmt.Sprintf("max-value-bytes=%d", config.Metadata.MaxValueBytes))
16601660
}
16611661
if len(metadataValues) != 0 {
1662-
config.Server.capValues[caps.MetadataTwoJudgementDay] = strings.Join(metadataValues, ",")
1662+
config.Server.capValues[caps.Metadata] = strings.Join(metadataValues, ",")
16631663
}
16641664

16651665
}

irc/getters.go

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -833,24 +833,32 @@ func (session *Session) isSubscribedTo(key string) bool {
833833
session.client.stateMutex.RLock()
834834
defer session.client.stateMutex.RUnlock()
835835

836-
return slices.Contains(session.metadataSubscriptions, key)
836+
if session.metadataSubscriptions == nil {
837+
return false
838+
}
839+
840+
return session.metadataSubscriptions.Has(key)
837841
}
838842

839843
func (session *Session) SubscribeTo(keys ...string) ([]string, error) {
840844
session.client.stateMutex.Lock()
841845
defer session.client.stateMutex.Unlock()
842846

847+
if session.metadataSubscriptions == nil {
848+
session.metadataSubscriptions = make(utils.HashSet[string])
849+
}
850+
843851
var added []string
844852

845853
maxSubs := session.client.server.Config().Metadata.MaxSubs
846854

847855
for _, k := range keys {
848-
if !slices.Contains(session.metadataSubscriptions, k) {
856+
if !session.metadataSubscriptions.Has(k) {
849857
if len(session.metadataSubscriptions) > maxSubs {
850858
return added, errMetadataTooManySubs
851859
}
852860
added = append(added, k)
853-
session.metadataSubscriptions = append(session.metadataSubscriptions, k)
861+
session.metadataSubscriptions.Add(k)
854862
}
855863
}
856864

@@ -863,27 +871,25 @@ func (session *Session) UnsubscribeFrom(keys ...string) []string {
863871

864872
var removed []string
865873

866-
new := slices.DeleteFunc(session.metadataSubscriptions,
867-
func(keyName string) bool {
868-
if slices.Contains(keys, keyName) {
869-
removed = append(removed, keyName)
870-
return true
871-
} else {
872-
return false
873-
}
874-
},
875-
)
874+
if session.metadataSubscriptions == nil {
875+
return []string{}
876+
}
876877

877-
session.metadataSubscriptions = new
878+
for k := range session.metadataSubscriptions {
879+
if slices.Contains(keys, k) {
880+
removed = append(removed, k)
881+
session.metadataSubscriptions.Remove(k)
882+
}
883+
}
878884

879885
return removed
880886
}
881887

882-
func (session *Session) MetadataSubscriptions() []string {
888+
func (session *Session) MetadataSubscriptions() utils.HashSet[string] {
883889
session.client.stateMutex.Lock()
884890
defer session.client.stateMutex.Unlock()
885891

886-
return slices.Clone(session.metadataSubscriptions)
892+
return maps.Clone(session.metadataSubscriptions)
887893
}
888894

889895
func (channel *Channel) GetMetadata(key string) (string, error) {
@@ -901,15 +907,15 @@ func (channel *Channel) SetMetadata(key string, value string) {
901907
channel.stateMutex.Lock()
902908

903909
if channel.metadata == nil {
904-
channel.metadata = make(MetadataStore)
910+
channel.metadata = make(map[string]string)
905911
}
906912

907913
channel.metadata[key] = value
908914
channel.stateMutex.Unlock()
909915
channel.MarkDirty(IncludeAllAttrs)
910916
}
911917

912-
func (channel *Channel) ListMetadata() MetadataStore {
918+
func (channel *Channel) ListMetadata() map[string]string {
913919
channel.stateMutex.RLock()
914920
defer channel.stateMutex.RUnlock()
915921

@@ -924,11 +930,11 @@ func (channel *Channel) DeleteMetadata(key string) {
924930
channel.MarkDirty(IncludeAllAttrs)
925931
}
926932

927-
func (channel *Channel) ClearMetadata() MetadataStore {
933+
func (channel *Channel) ClearMetadata() map[string]string {
928934
channel.stateMutex.Lock()
929935

930936
oldMap := channel.metadata
931-
channel.metadata = make(MetadataStore)
937+
channel.metadata = make(map[string]string)
932938

933939
channel.stateMutex.Unlock()
934940
channel.MarkDirty(IncludeAllAttrs)
@@ -962,15 +968,13 @@ func (client *Client) SetMetadata(key string, value string) {
962968
defer client.stateMutex.Unlock()
963969

964970
if client.metadata == nil {
965-
client.metadata = make(MetadataStore)
971+
client.metadata = make(map[string]string)
966972
}
967973

968974
client.metadata[key] = value
969-
970-
// coming soon: https://www.youtube.com/watch?v=K14JkFfWUzc
971975
}
972976

973-
func (client *Client) ListMetadata() MetadataStore {
977+
func (client *Client) ListMetadata() map[string]string {
974978
client.stateMutex.RLock()
975979
defer client.stateMutex.RUnlock()
976980

@@ -984,12 +988,12 @@ func (client *Client) DeleteMetadata(key string) {
984988
delete(client.metadata, key)
985989
}
986990

987-
func (client *Client) ClearMetadata() MetadataStore {
991+
func (client *Client) ClearMetadata() map[string]string {
988992
client.stateMutex.Lock()
989993
defer client.stateMutex.Unlock()
990994

991995
oldMap := client.metadata
992-
client.metadata = make(MetadataStore)
996+
client.metadata = make(map[string]string)
993997

994998
return oldMap
995999
}

irc/handlers.go

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ package irc
99
import (
1010
"bytes"
1111
"fmt"
12+
"maps"
1213
"net"
1314
"os"
1415
"runtime"
1516
"runtime/debug"
1617
"runtime/pprof"
18+
"slices"
1719
"sort"
1820
"strconv"
1921
"strings"
@@ -3248,10 +3250,10 @@ func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res
32483250

32493251
lineLength := MaxLineLen - len(server.name) - len(RPL_METADATASUBOK) - len(client.Nick()) - 10
32503252

3251-
chunked := utils.ChunkifyParams(added, lineLength)
3253+
chunked := utils.ChunkifyParams(slices.Values(added), lineLength)
32523254
for _, line := range chunked {
32533255
params := append([]string{client.Nick()}, line...)
3254-
rb.Add(nil, server.name, RPL_METADATASUBS, params...)
3256+
rb.Add(nil, server.name, RPL_METADATASUBOK, params...)
32553257
}
32563258

32573259
case "unsub":
@@ -3260,42 +3262,29 @@ func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res
32603262
removed := rb.session.UnsubscribeFrom(keys...)
32613263

32623264
lineLength := MaxLineLen - len(server.name) - len(RPL_METADATAUNSUBOK) - len(client.Nick()) - 10
3263-
chunked := utils.ChunkifyParams(removed, lineLength)
3265+
chunked := utils.ChunkifyParams(slices.Values(removed), lineLength)
32643266
for _, line := range chunked {
32653267
params := append([]string{client.Nick()}, line...)
3266-
rb.Add(nil, server.name, RPL_METADATASUBS, params...)
3268+
rb.Add(nil, server.name, RPL_METADATAUNSUBOK, params...)
32673269
}
32683270

32693271
case "subs":
32703272
lineLength := MaxLineLen - len(server.name) - len(RPL_METADATASUBS) - len(client.Nick()) - 10 // for safety
32713273

3272-
chunked := utils.ChunkifyParams(rb.session.MetadataSubscriptions(), lineLength)
3274+
subs := rb.session.MetadataSubscriptions()
3275+
3276+
chunked := utils.ChunkifyParams(maps.Keys(subs), lineLength)
32733277
for _, line := range chunked {
32743278
params := append([]string{client.Nick()}, line...)
32753279
rb.Add(nil, server.name, RPL_METADATASUBS, params...)
32763280
}
32773281

32783282
case "sync":
3279-
batchId := rb.StartNestedBatch("metadata")
3280-
defer rb.EndNestedBatch(batchId)
3281-
3282-
values := t.ListMetadata()
3283-
for k, v := range values {
3284-
if rb.session.isSubscribedTo(k) {
3285-
visibility := "*"
3286-
rb.Add(nil, server.name, "METADATA", target, k, visibility, v)
3287-
}
3288-
}
32893283
if targetChannel != nil {
3290-
for _, client := range targetChannel.Members() {
3291-
values := client.ListMetadata()
3292-
for k, v := range values {
3293-
if rb.session.isSubscribedTo(k) {
3294-
visibility := "*"
3295-
rb.Add(nil, server.name, "METADATA", client.Nick(), k, visibility, v)
3296-
}
3297-
}
3298-
}
3284+
syncChannelMetadata(server, rb, targetChannel)
3285+
}
3286+
if targetClient != nil {
3287+
syncClientMetadata(server, rb, targetClient)
32993288
}
33003289

33013290
default:

irc/metadata.go

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,12 @@ var (
1515
errMetadataNotFound = errors.New("key not found")
1616
)
1717

18-
type MetadataStore = map[string]string
19-
2018
type MetadataHaver = interface {
2119
SetMetadata(key string, value string)
2220
GetMetadata(key string) (string, error)
2321
DeleteMetadata(key string)
24-
ListMetadata() MetadataStore
25-
ClearMetadata() MetadataStore
22+
ListMetadata() map[string]string
23+
ClearMetadata() map[string]string
2624
CountMetadata() int
2725
}
2826

@@ -32,7 +30,7 @@ func notifySubscribers(server *Server, session *Session, target string, key stri
3230
targetClient := server.clients.Get(target)
3331

3432
if targetClient != nil {
35-
notify = targetClient.FriendsMonitors(caps.MetadataTwoJudgementDay)
33+
notify = targetClient.FriendsMonitors(caps.Metadata)
3634
// notify clients about changes regarding themselves
3735
for _, s := range targetClient.Sessions() {
3836
notify.Add(s)
@@ -42,7 +40,7 @@ func notifySubscribers(server *Server, session *Session, target string, key stri
4240
members := targetChannel.Members()
4341
for _, m := range members {
4442
for _, s := range m.Sessions() {
45-
if s.capabilities.Has(caps.MetadataTwoJudgementDay) {
43+
if s.capabilities.Has(caps.Metadata) {
4644
notify.Add(s)
4745
}
4846
}
@@ -65,6 +63,42 @@ func notifySubscribers(server *Server, session *Session, target string, key stri
6563
}
6664
}
6765

66+
func syncClientMetadata(server *Server, rb *ResponseBuffer, target *Client) {
67+
batchId := rb.StartNestedBatch("metadata")
68+
defer rb.EndNestedBatch(batchId)
69+
70+
values := target.ListMetadata()
71+
for k, v := range values {
72+
if rb.session.isSubscribedTo(k) {
73+
visibility := "*"
74+
rb.Add(nil, server.name, "METADATA", target.Nick(), k, visibility, v)
75+
}
76+
}
77+
}
78+
79+
func syncChannelMetadata(server *Server, rb *ResponseBuffer, target *Channel) {
80+
batchId := rb.StartNestedBatch("metadata")
81+
defer rb.EndNestedBatch(batchId)
82+
83+
values := target.ListMetadata()
84+
for k, v := range values {
85+
if rb.session.isSubscribedTo(k) {
86+
visibility := "*"
87+
rb.Add(nil, server.name, "METADATA", target.Name(), k, visibility, v)
88+
}
89+
}
90+
91+
for _, client := range target.Members() {
92+
values := client.ListMetadata()
93+
for k, v := range values {
94+
if rb.session.isSubscribedTo(k) {
95+
visibility := "*"
96+
rb.Add(nil, server.name, "METADATA", client.Nick(), k, visibility, v)
97+
}
98+
}
99+
}
100+
}
101+
68102
var metadataEvilCharsRegexp = regexp.MustCompile("[^A-Za-z0-9_./:-]+")
69103

70104
func metadataKeyIsEvil(key string) bool {

0 commit comments

Comments
 (0)