Skip to content

Commit 7586520

Browse files
authored
implement draft/extended-isupport (#2184)
1 parent f68d32b commit 7586520

File tree

8 files changed

+57
-10
lines changed

8 files changed

+57
-10
lines changed

gencapdefs.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,12 @@
219219
url="https://github.com/ircv3/ircv3-specifications/pull/527",
220220
standard="proposed IRCv3",
221221
),
222+
CapDef(
223+
identifier="ExtendedISupport",
224+
name="draft/extended-isupport",
225+
url="https://github.com/ircv3/ircv3-specifications/pull/543",
226+
standard="proposed IRCv3",
227+
),
222228
]
223229

224230
def validate_defs():

irc/caps/constants.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,11 @@ const (
6464
BotTagName = "bot"
6565
// https://ircv3.net/specs/extensions/chathistory
6666
ChathistoryTargetsBatchType = "draft/chathistory-targets"
67+
ExtendedISupportBatchType = "draft/extended-isupport"
6768
)
6869

6970
func init() {
70-
nameToCapability = make(map[string]Capability)
71+
nameToCapability = make(map[string]Capability, numCapabs)
7172
for capab, name := range capabilityNames {
7273
nameToCapability[name] = Capability(capab)
7374
}

irc/caps/defs.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ package caps
77

88
const (
99
// number of recognized capabilities:
10-
numCapabs = 34
10+
numCapabs = 35
1111
// length of the uint32 array that represents the bitset:
1212
bitsetLen = 2
1313
)
@@ -53,6 +53,10 @@ const (
5353
// https://github.com/ircv3/ircv3-specifications/pull/362
5454
EventPlayback Capability = iota
5555

56+
// ExtendedISupport is the proposed IRCv3 capability named "draft/extended-isupport":
57+
// https://github.com/ircv3/ircv3-specifications/pull/543
58+
ExtendedISupport Capability = iota
59+
5660
// Languages is the proposed IRCv3 capability named "draft/languages":
5761
// https://gist.github.com/DanielOaks/8126122f74b26012a3de37db80e4e0c6
5862
Languages Capability = iota
@@ -163,6 +167,7 @@ var (
163167
"draft/channel-rename",
164168
"draft/chathistory",
165169
"draft/event-playback",
170+
"draft/extended-isupport",
166171
"draft/languages",
167172
"draft/message-redaction",
168173
"draft/multiline",

irc/client.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ type Session struct {
179179

180180
batchCounter atomic.Uint32
181181

182+
isupportSentPrereg bool
183+
182184
quitMessage string
183185

184186
awayMessage string

irc/commands.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ func init() {
152152
handler: isonHandler,
153153
minParams: 1,
154154
},
155+
"ISUPPORT": {
156+
handler: isupportHandler,
157+
usablePreReg: true,
158+
},
155159
"JOIN": {
156160
handler: joinHandler,
157161
minParams: 1,

irc/handlers.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,15 @@ func isonHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respons
13201320
return false
13211321
}
13221322

1323+
// ISUPPORT
1324+
func isupportHandler(server *Server, client *Client, msg ircmsg.Message, rb *ResponseBuffer) bool {
1325+
server.RplISupport(client, rb)
1326+
if !client.registered {
1327+
rb.session.isupportSentPrereg = true
1328+
}
1329+
return false
1330+
}
1331+
13231332
// JOIN <channel>{,<channel>} [<key>{,<key>}]
13241333
func joinHandler(server *Server, client *Client, msg ircmsg.Message, rb *ResponseBuffer) bool {
13251334
// #1417: allow `JOIN 0` with a confirmation code

irc/help.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,11 @@ appropriate channel privs.`,
259259
text: `ISON <nickname>{ <nickname>}
260260
261261
Returns whether the given nicks exist on the network.`,
262+
},
263+
"isupport": {
264+
text: `ISUPPORT
265+
266+
Returns RPL_ISUPPORT lines describing the server's capabilities.`,
262267
},
263268
"join": {
264269
text: `JOIN <channel>{,<channel>} [<key>{,<key>}]

irc/server.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,9 @@ func (server *Server) playRegistrationBurst(session *Session) {
434434
session.Send(nil, server.name, RPL_MYINFO, d.nick, server.name, Ver, rplMyInfo1, rplMyInfo2, rplMyInfo3)
435435

436436
rb := NewResponseBuffer(session)
437-
server.RplISupport(c, rb)
437+
if !(rb.session.capabilities.Has(caps.ExtendedISupport) && rb.session.isupportSentPrereg) {
438+
server.RplISupport(c, rb)
439+
}
438440
if d.account != "" && session.capabilities.Has(caps.Persistence) {
439441
reportPersistenceStatus(c, rb, false)
440442
}
@@ -456,10 +458,17 @@ func (server *Server) playRegistrationBurst(session *Session) {
456458

457459
// RplISupport outputs our ISUPPORT lines to the client. This is used on connection and in VERSION responses.
458460
func (server *Server) RplISupport(client *Client, rb *ResponseBuffer) {
461+
server.sendRplISupportLines(client, rb, server.Config().Server.isupport.CachedReply)
462+
}
463+
464+
func (server *Server) sendRplISupportLines(client *Client, rb *ResponseBuffer, lines [][]string) {
465+
if rb.session.capabilities.Has(caps.ExtendedISupport) {
466+
batchID := rb.StartNestedBatch("chathistory", caps.ExtendedISupportBatchType)
467+
defer rb.EndNestedBatch(batchID)
468+
}
459469
translatedISupport := client.t("are supported by this server")
460470
nick := client.Nick()
461-
config := server.Config()
462-
for _, cachedTokenLine := range config.Server.isupport.CachedReply {
471+
for _, cachedTokenLine := range lines {
463472
length := len(cachedTokenLine) + 2
464473
tokenline := make([]string, length)
465474
tokenline[0] = nick
@@ -794,13 +803,19 @@ func (server *Server) applyConfig(config *Config) (err error) {
794803
}
795804

796805
if !initial {
797-
// push new info to all of our clients
798-
for _, sClient := range server.clients.AllClients() {
799-
for _, tokenline := range newISupportReplies {
800-
sClient.Send(nil, server.name, RPL_ISUPPORT, append([]string{sClient.nick}, tokenline...)...)
806+
// send 005 updates (somewhat rare)
807+
if len(newISupportReplies) != 0 {
808+
for _, sClient := range server.clients.AllClients() {
809+
for _, session := range sClient.Sessions() {
810+
rb := NewResponseBuffer(session)
811+
server.sendRplISupportLines(sClient, rb, newISupportReplies)
812+
rb.Send(false)
813+
}
801814
}
815+
}
802816

803-
if sendRawOutputNotice {
817+
if sendRawOutputNotice {
818+
for _, sClient := range server.clients.AllClients() {
804819
sClient.Notice(sClient.t("This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
805820
}
806821
}

0 commit comments

Comments
 (0)