Compare commits
10 commits
d5108f3994
...
9bd3bebd19
Author | SHA1 | Date | |
---|---|---|---|
Gabriel Simmer | 9bd3bebd19 | ||
0c86b96e86 | |||
9e0d0b0ff4 | |||
75a58cc2cb | |||
3a4e54bc45 | |||
6d0f7330e3 | |||
0ecc9cd042 | |||
c36140fb2a | |||
6b13ca5f34 | |||
51a12983d8 |
19
Containerfile
Normal file
19
Containerfile
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
FROM golang:1.21.6-bookworm as build
|
||||||
|
|
||||||
|
ENV CGO_ENABLED=0 \
|
||||||
|
GOOS=linux \
|
||||||
|
GOFLAGS="-tags=moderncsqlite"
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
COPY . /build
|
||||||
|
|
||||||
|
RUN make soju
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=build /build/soju /app/soju
|
||||||
|
COPY --from=build /build/sojuctl /app/sojuctl
|
||||||
|
COPY --from=build /build/sojudb /app/sojudb
|
||||||
|
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||||
|
|
||||||
|
CMD ["/app/soju"]
|
|
@ -134,10 +134,6 @@ func main() {
|
||||||
cfg.Listen = []string{":6697"}
|
cfg.Listen = []string{":6697"}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := bumpOpenedFileLimit(); err != nil {
|
|
||||||
log.Printf("failed to bump max number of opened files: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
db, err := database.Open(cfg.DB.Driver, cfg.DB.Source)
|
db, err := database.Open(cfg.DB.Driver, cfg.DB.Source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to open database: %v", err)
|
log.Fatalf("failed to open database: %v", err)
|
||||||
|
@ -227,6 +223,9 @@ func main() {
|
||||||
log.Fatalf("failed to start listener on %q: %v", listen, err)
|
log.Fatalf("failed to start listener on %q: %v", listen, err)
|
||||||
}
|
}
|
||||||
ln = proxyProtoListener(ln, srv)
|
ln = proxyProtoListener(ln, srv)
|
||||||
|
if err := os.Chmod(u.Path, 0775); err != nil {
|
||||||
|
log.Printf("failed to chmod Unix IRC socket: %v", err)
|
||||||
|
}
|
||||||
go func() {
|
go func() {
|
||||||
if err := srv.Serve(ln, srv.Handle); err != nil {
|
if err := srv.Serve(ln, srv.Handle); err != nil {
|
||||||
log.Printf("serving %q: %v", listen, err)
|
log.Printf("serving %q: %v", listen, err)
|
||||||
|
@ -280,6 +279,9 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to start listener on %q: %v", listen, err)
|
log.Fatalf("failed to start listener on %q: %v", listen, err)
|
||||||
}
|
}
|
||||||
|
if err := os.Chmod(u.Path, 0775); err != nil {
|
||||||
|
log.Printf("failed to chmod Unix WS socket: %v", err)
|
||||||
|
}
|
||||||
go func() {
|
go func() {
|
||||||
if err := http.Serve(ln, srv); err != nil {
|
if err := http.Serve(ln, srv); err != nil {
|
||||||
log.Fatalf("serving %q: %v", listen, err)
|
log.Fatalf("serving %q: %v", listen, err)
|
||||||
|
@ -381,6 +383,9 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to start listener on %q: %v", listen, err)
|
log.Fatalf("failed to start listener on %q: %v", listen, err)
|
||||||
}
|
}
|
||||||
|
if err := os.Chmod(u.Path, 0775); err != nil {
|
||||||
|
log.Printf("failed to chmod Unix HTTP socket: %v", err)
|
||||||
|
}
|
||||||
go func() {
|
go func() {
|
||||||
if err := http.Serve(ln, httpMux); err != nil {
|
if err := http.Serve(ln, httpMux); err != nil {
|
||||||
log.Fatalf("serving %q: %v", listen, err)
|
log.Fatalf("serving %q: %v", listen, err)
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func bumpOpenedFileLimit() error {
|
|
||||||
var rlimit syscall.Rlimit
|
|
||||||
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
|
|
||||||
return fmt.Errorf("failed to get RLIMIT_NOFILE: %v", err)
|
|
||||||
}
|
|
||||||
rlimit.Cur = rlimit.Max
|
|
||||||
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
|
|
||||||
return fmt.Errorf("failed to set RLIMIT_NOFILE: %v", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
func bumpOpenedFileLimit() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -483,9 +483,11 @@ character.
|
||||||
*-network* <name>
|
*-network* <name>
|
||||||
Select a network. By default, the current network is selected, if any.
|
Select a network. By default, the current network is selected, if any.
|
||||||
|
|
||||||
*user status*
|
*user status* [username]
|
||||||
Show a list of users on this server. Only admins can query this information.
|
Show a list of users on this server. Only admins can query this information.
|
||||||
|
|
||||||
|
If _username_ is specified, statistics are only displayed for this user.
|
||||||
|
|
||||||
*user create* -username <username> -password <password> [options...]
|
*user create* -username <username> -password <password> [options...]
|
||||||
Create a new soju user. Only admin users can create new accounts.
|
Create a new soju user. Only admin users can create new accounts.
|
||||||
The _-username_ and _-password_ flags are mandatory.
|
The _-username_ and _-password_ flags are mandatory.
|
||||||
|
|
|
@ -530,6 +530,12 @@ func (dc *downstreamConn) SendMessage(ctx context.Context, msg *irc.Message) {
|
||||||
msg = &msgCopy
|
msg = &msgCopy
|
||||||
msg.Prefix = nil
|
msg.Prefix = nil
|
||||||
}
|
}
|
||||||
|
if msg.Prefix == nil && isNumeric(msg.Command) {
|
||||||
|
// Numerics must always carry a source
|
||||||
|
msgCopy := *msg
|
||||||
|
msg = &msgCopy
|
||||||
|
msg.Prefix = dc.srv.prefix()
|
||||||
|
}
|
||||||
|
|
||||||
dc.srv.metrics.downstreamOutMessagesTotal.Inc()
|
dc.srv.metrics.downstreamOutMessagesTotal.Inc()
|
||||||
dc.conn.SendMessage(ctx, msg)
|
dc.conn.SendMessage(ctx, msg)
|
||||||
|
@ -542,7 +548,6 @@ func (dc *downstreamConn) SendBatch(ctx context.Context, typ string, params []st
|
||||||
if dc.caps.IsEnabled("batch") {
|
if dc.caps.IsEnabled("batch") {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Tags: tags,
|
Tags: tags,
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "BATCH",
|
Command: "BATCH",
|
||||||
Params: append([]string{"+" + ref, typ}, params...),
|
Params: append([]string{"+" + ref, typ}, params...),
|
||||||
})
|
})
|
||||||
|
@ -552,7 +557,6 @@ func (dc *downstreamConn) SendBatch(ctx context.Context, typ string, params []st
|
||||||
|
|
||||||
if dc.caps.IsEnabled("batch") {
|
if dc.caps.IsEnabled("batch") {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "BATCH",
|
Command: "BATCH",
|
||||||
Params: []string{"-" + ref},
|
Params: []string{"-" + ref},
|
||||||
})
|
})
|
||||||
|
@ -697,7 +701,6 @@ func (dc *downstreamConn) handleMessageUnregistered(ctx context.Context, msg *ir
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dc.logger.Printf("SASL %v authentication error for nick %q: %v", credentials.mechanism, dc.registration.nick, err)
|
dc.logger.Printf("SASL %v authentication error for nick %q: %v", credentials.mechanism, dc.registration.nick, err)
|
||||||
dc.endSASL(ctx, &irc.Message{
|
dc.endSASL(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{dc.nick, authErrorReason(err)},
|
Params: []string{dc.nick, authErrorReason(err)},
|
||||||
})
|
})
|
||||||
|
@ -753,7 +756,7 @@ func (dc *downstreamConn) handleMessageUnregistered(ctx context.Context, msg *ir
|
||||||
dc.away = nil
|
dc.away = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SendMessage(ctx, generateAwayReply(dc.away != nil, dc.srv.prefix()))
|
dc.SendMessage(ctx, generateAwayReply(dc.away != nil))
|
||||||
default:
|
default:
|
||||||
dc.logger.Debugf("unhandled message: %v", msg)
|
dc.logger.Debugf("unhandled message: %v", msg)
|
||||||
return newUnknownCommandError(msg.Command)
|
return newUnknownCommandError(msg.Command)
|
||||||
|
@ -905,21 +908,18 @@ func (dc *downstreamConn) handleAuthenticate(ctx context.Context, msg *irc.Messa
|
||||||
|
|
||||||
if !dc.caps.IsEnabled("sasl") {
|
if !dc.caps.IsEnabled("sasl") {
|
||||||
return nil, ircError{&irc.Message{
|
return nil, ircError{&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{dc.nick, "AUTHENTICATE requires the \"sasl\" capability to be enabled"},
|
Params: []string{dc.nick, "AUTHENTICATE requires the \"sasl\" capability to be enabled"},
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
if len(msg.Params) == 0 {
|
if len(msg.Params) == 0 {
|
||||||
return nil, ircError{&irc.Message{
|
return nil, ircError{&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{dc.nick, "Missing AUTHENTICATE argument"},
|
Params: []string{dc.nick, "Missing AUTHENTICATE argument"},
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
if msg.Params[0] == "*" {
|
if msg.Params[0] == "*" {
|
||||||
return nil, ircError{&irc.Message{
|
return nil, ircError{&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_SASLABORTED,
|
Command: irc.ERR_SASLABORTED,
|
||||||
Params: []string{dc.nick, "SASL authentication aborted"},
|
Params: []string{dc.nick, "SASL authentication aborted"},
|
||||||
}}
|
}}
|
||||||
|
@ -952,7 +952,6 @@ func (dc *downstreamConn) handleAuthenticate(ctx context.Context, msg *irc.Messa
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
return nil, ircError{&irc.Message{
|
return nil, ircError{&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{dc.nick, "Unsupported SASL mechanism"},
|
Params: []string{dc.nick, "Unsupported SASL mechanism"},
|
||||||
}}
|
}}
|
||||||
|
@ -967,7 +966,6 @@ func (dc *downstreamConn) handleAuthenticate(ctx context.Context, msg *irc.Messa
|
||||||
|
|
||||||
if dc.sasl.pendingResp.Len()+len(chunk) > 10*1024 {
|
if dc.sasl.pendingResp.Len()+len(chunk) > 10*1024 {
|
||||||
return nil, ircError{&irc.Message{
|
return nil, ircError{&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{dc.nick, "Response too long"},
|
Params: []string{dc.nick, "Response too long"},
|
||||||
}}
|
}}
|
||||||
|
@ -982,7 +980,6 @@ func (dc *downstreamConn) handleAuthenticate(ctx context.Context, msg *irc.Messa
|
||||||
resp, err = base64.StdEncoding.DecodeString(dc.sasl.pendingResp.String())
|
resp, err = base64.StdEncoding.DecodeString(dc.sasl.pendingResp.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ircError{&irc.Message{
|
return nil, ircError{&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{dc.nick, "Invalid base64-encoded response"},
|
Params: []string{dc.nick, "Invalid base64-encoded response"},
|
||||||
}}
|
}}
|
||||||
|
@ -1004,7 +1001,6 @@ func (dc *downstreamConn) handleAuthenticate(ctx context.Context, msg *irc.Messa
|
||||||
|
|
||||||
// TODO: multi-line messages
|
// TODO: multi-line messages
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "AUTHENTICATE",
|
Command: "AUTHENTICATE",
|
||||||
Params: []string{challengeStr},
|
Params: []string{challengeStr},
|
||||||
})
|
})
|
||||||
|
@ -1023,7 +1019,6 @@ func (dc *downstreamConn) endSASL(ctx context.Context, msg *irc.Message) {
|
||||||
dc.SendMessage(ctx, msg)
|
dc.SendMessage(ctx, msg)
|
||||||
} else {
|
} else {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_SASLSUCCESS,
|
Command: irc.RPL_SASLSUCCESS,
|
||||||
Params: []string{dc.nick, "SASL authentication successful"},
|
Params: []string{dc.nick, "SASL authentication successful"},
|
||||||
})
|
})
|
||||||
|
@ -1204,13 +1199,11 @@ func (dc *downstreamConn) updateAccount(ctx context.Context) {
|
||||||
|
|
||||||
if account != "" {
|
if account != "" {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_LOGGEDIN,
|
Command: irc.RPL_LOGGEDIN,
|
||||||
Params: []string{dc.nick, dc.prefix().String(), account, "You are logged in as " + account},
|
Params: []string{dc.nick, dc.prefix().String(), account, "You are logged in as " + account},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_LOGGEDOUT,
|
Command: irc.RPL_LOGGEDOUT,
|
||||||
Params: []string{dc.nick, dc.prefix().String(), "You are logged out"},
|
Params: []string{dc.nick, dc.prefix().String(), "You are logged out"},
|
||||||
})
|
})
|
||||||
|
@ -1281,7 +1274,6 @@ func (dc *downstreamConn) register(ctx context.Context) error {
|
||||||
|
|
||||||
if dc.sasl != nil {
|
if dc.sasl != nil {
|
||||||
dc.endSASL(ctx, &irc.Message{
|
dc.endSASL(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_SASLABORTED,
|
Command: irc.ERR_SASLABORTED,
|
||||||
Params: []string{dc.nick, "SASL authentication aborted"},
|
Params: []string{dc.nick, "SASL authentication aborted"},
|
||||||
})
|
})
|
||||||
|
@ -1499,33 +1491,28 @@ func (dc *downstreamConn) welcome(ctx context.Context, user *user) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_WELCOME,
|
Command: irc.RPL_WELCOME,
|
||||||
Params: []string{dc.nick, "Welcome to soju, " + dc.nick},
|
Params: []string{dc.nick, "Welcome to soju, " + dc.nick},
|
||||||
})
|
})
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_YOURHOST,
|
Command: irc.RPL_YOURHOST,
|
||||||
Params: []string{dc.nick, "Your host is " + dc.srv.Config().Hostname},
|
Params: []string{dc.nick, "Your host is " + dc.srv.Config().Hostname},
|
||||||
})
|
})
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_MYINFO,
|
Command: irc.RPL_MYINFO,
|
||||||
Params: []string{dc.nick, dc.srv.Config().Hostname, "soju", "aiwroO", "OovaimnqpsrtklbeI"},
|
Params: []string{dc.nick, dc.srv.Config().Hostname, "soju", "aiwroO", "OovaimnqpsrtklbeI"},
|
||||||
})
|
})
|
||||||
for _, msg := range xirc.GenerateIsupport(dc.srv.prefix(), isupport) {
|
for _, msg := range xirc.GenerateIsupport(isupport) {
|
||||||
dc.SendMessage(ctx, msg)
|
dc.SendMessage(ctx, msg)
|
||||||
}
|
}
|
||||||
if uc := dc.upstream(); uc != nil {
|
if uc := dc.upstream(); uc != nil {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_UMODEIS,
|
Command: irc.RPL_UMODEIS,
|
||||||
Params: []string{dc.nick, "+" + string(uc.modes)},
|
Params: []string{dc.nick, "+" + string(uc.modes)},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if dc.network == nil && dc.user.Admin {
|
if dc.network == nil && dc.user.Admin {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_UMODEIS,
|
Command: irc.RPL_UMODEIS,
|
||||||
Params: []string{dc.nick, "+o"},
|
Params: []string{dc.nick, "+o"},
|
||||||
})
|
})
|
||||||
|
@ -1537,7 +1524,7 @@ func (dc *downstreamConn) welcome(ctx context.Context, user *user) error {
|
||||||
dc.updateCasemapping()
|
dc.updateCasemapping()
|
||||||
|
|
||||||
if motd := dc.user.srv.Config().MOTD; motd != "" && dc.network == nil {
|
if motd := dc.user.srv.Config().MOTD; motd != "" && dc.network == nil {
|
||||||
for _, msg := range xirc.GenerateMOTD(dc.srv.prefix(), motd) {
|
for _, msg := range xirc.GenerateMOTD(motd) {
|
||||||
dc.SendMessage(ctx, msg)
|
dc.SendMessage(ctx, msg)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1546,7 +1533,6 @@ func (dc *downstreamConn) welcome(ctx context.Context, user *user) error {
|
||||||
motdHint = "Use /motd to read the message of the day"
|
motdHint = "Use /motd to read the message of the day"
|
||||||
}
|
}
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_NOMOTD,
|
Command: irc.ERR_NOMOTD,
|
||||||
Params: []string{dc.nick, motdHint},
|
Params: []string{dc.nick, motdHint},
|
||||||
})
|
})
|
||||||
|
@ -1559,7 +1545,6 @@ func (dc *downstreamConn) welcome(ctx context.Context, user *user) error {
|
||||||
attrs := getNetworkAttrs(network)
|
attrs := getNetworkAttrs(network)
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Tags: irc.Tags{"batch": batchRef},
|
Tags: irc.Tags{"batch": batchRef},
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "BOUNCER",
|
Command: "BOUNCER",
|
||||||
Params: []string{"NETWORK", idStr, attrs.String()},
|
Params: []string{"NETWORK", idStr, attrs.String()},
|
||||||
})
|
})
|
||||||
|
@ -1903,7 +1888,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
|
|
||||||
if name == "" || strings.ContainsAny(name, illegalChanChars) {
|
if name == "" || strings.ContainsAny(name, illegalChanChars) {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_BADCHANMASK,
|
Command: irc.ERR_BADCHANMASK,
|
||||||
Params: []string{name, "Invalid channel name"},
|
Params: []string{name, "Invalid channel name"},
|
||||||
})
|
})
|
||||||
|
@ -1911,7 +1895,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
}
|
}
|
||||||
if !uc.isChannel(name) {
|
if !uc.isChannel(name) {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_NOSUCHCHANNEL,
|
Command: irc.ERR_NOSUCHCHANNEL,
|
||||||
Params: []string{name, "Not a channel name"},
|
Params: []string{name, "Not a channel name"},
|
||||||
})
|
})
|
||||||
|
@ -2032,7 +2015,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_UMODEIS,
|
Command: irc.RPL_UMODEIS,
|
||||||
Params: []string{dc.nick, "+" + userMode},
|
Params: []string{dc.nick, "+" + userMode},
|
||||||
})
|
})
|
||||||
|
@ -2078,13 +2060,11 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
params = append(params, modeParams...)
|
params = append(params, modeParams...)
|
||||||
|
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_CHANNELMODEIS,
|
Command: irc.RPL_CHANNELMODEIS,
|
||||||
Params: params,
|
Params: params,
|
||||||
})
|
})
|
||||||
if ch.creationTime != "" {
|
if ch.creationTime != "" {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: xirc.RPL_CREATIONTIME,
|
Command: xirc.RPL_CREATIONTIME,
|
||||||
Params: []string{dc.nick, name, ch.creationTime},
|
Params: []string{dc.nick, name, ch.creationTime},
|
||||||
})
|
})
|
||||||
|
@ -2131,7 +2111,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
|
|
||||||
if len(msg.Params) == 0 {
|
if len(msg.Params) == 0 {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_ENDOFNAMES,
|
Command: irc.RPL_ENDOFNAMES,
|
||||||
Params: []string{dc.nick, "*", "End of /NAMES list"},
|
Params: []string{dc.nick, "*", "End of /NAMES list"},
|
||||||
})
|
})
|
||||||
|
@ -2154,7 +2133,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
case "WHO":
|
case "WHO":
|
||||||
if len(msg.Params) == 0 {
|
if len(msg.Params) == 0 {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_ENDOFWHO,
|
Command: irc.RPL_ENDOFWHO,
|
||||||
Params: []string{"*", "*", "End of /WHO list"},
|
Params: []string{"*", "*", "End of /WHO list"},
|
||||||
})
|
})
|
||||||
|
@ -2191,9 +2169,8 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
Account: dc.user.Username,
|
Account: dc.user.Username,
|
||||||
Realname: dc.realname,
|
Realname: dc.realname,
|
||||||
}
|
}
|
||||||
dc.SendMessage(ctx, xirc.GenerateWHOXReply(dc.srv.prefix(), fields, &info))
|
dc.SendMessage(ctx, xirc.GenerateWHOXReply(fields, &info))
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_ENDOFWHO,
|
Command: irc.RPL_ENDOFWHO,
|
||||||
Params: []string{"*", endOfWhoToken, "End of /WHO list"},
|
Params: []string{"*", endOfWhoToken, "End of /WHO list"},
|
||||||
})
|
})
|
||||||
|
@ -2218,9 +2195,8 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
Account: serviceNick,
|
Account: serviceNick,
|
||||||
Realname: serviceRealname,
|
Realname: serviceRealname,
|
||||||
}
|
}
|
||||||
dc.SendMessage(ctx, xirc.GenerateWHOXReply(dc.srv.prefix(), fields, &info))
|
dc.SendMessage(ctx, xirc.GenerateWHOXReply(fields, &info))
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_ENDOFWHO,
|
Command: irc.RPL_ENDOFWHO,
|
||||||
Params: []string{"*", endOfWhoToken, "End of /WHO list"},
|
Params: []string{"*", endOfWhoToken, "End of /WHO list"},
|
||||||
})
|
})
|
||||||
|
@ -2228,7 +2204,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
}
|
}
|
||||||
if dc.network == nil {
|
if dc.network == nil {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_ENDOFWHO,
|
Command: irc.RPL_ENDOFWHO,
|
||||||
Params: []string{"*", endOfWhoToken, "End of /WHO list"},
|
Params: []string{"*", endOfWhoToken, "End of /WHO list"},
|
||||||
})
|
})
|
||||||
|
@ -2256,10 +2231,9 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
if uc.isChannel(mask) {
|
if uc.isChannel(mask) {
|
||||||
info.Channel = mask
|
info.Channel = mask
|
||||||
}
|
}
|
||||||
dc.SendMessage(ctx, xirc.GenerateWHOXReply(dc.srv.prefix(), fields, &info))
|
dc.SendMessage(ctx, xirc.GenerateWHOXReply(fields, &info))
|
||||||
}
|
}
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_ENDOFWHO,
|
Command: irc.RPL_ENDOFWHO,
|
||||||
Params: []string{"*", endOfWhoToken, "End of /WHO list"},
|
Params: []string{"*", endOfWhoToken, "End of /WHO list"},
|
||||||
})
|
})
|
||||||
|
@ -2288,29 +2262,24 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
|
|
||||||
if dc.network == nil && dc.casemap(mask) == dc.nickCM {
|
if dc.network == nil && dc.casemap(mask) == dc.nickCM {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_WHOISUSER,
|
Command: irc.RPL_WHOISUSER,
|
||||||
Params: []string{dc.nick, dc.nick, dc.user.Username, dc.hostname, "*", dc.realname},
|
Params: []string{dc.nick, dc.nick, dc.user.Username, dc.hostname, "*", dc.realname},
|
||||||
})
|
})
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_WHOISSERVER,
|
Command: irc.RPL_WHOISSERVER,
|
||||||
Params: []string{dc.nick, dc.nick, dc.srv.Config().Hostname, "soju"},
|
Params: []string{dc.nick, dc.nick, dc.srv.Config().Hostname, "soju"},
|
||||||
})
|
})
|
||||||
if dc.user.Admin {
|
if dc.user.Admin {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_WHOISOPERATOR,
|
Command: irc.RPL_WHOISOPERATOR,
|
||||||
Params: []string{dc.nick, dc.nick, "is a bouncer administrator"},
|
Params: []string{dc.nick, dc.nick, "is a bouncer administrator"},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: xirc.RPL_WHOISACCOUNT,
|
Command: xirc.RPL_WHOISACCOUNT,
|
||||||
Params: []string{dc.nick, dc.nick, dc.user.Username, "is logged in as"},
|
Params: []string{dc.nick, dc.nick, dc.user.Username, "is logged in as"},
|
||||||
})
|
})
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_ENDOFWHOIS,
|
Command: irc.RPL_ENDOFWHOIS,
|
||||||
Params: []string{dc.nick, dc.nick, "End of /WHOIS list"},
|
Params: []string{dc.nick, dc.nick, "End of /WHOIS list"},
|
||||||
})
|
})
|
||||||
|
@ -2318,32 +2287,26 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
}
|
}
|
||||||
if dc.casemap(mask) == serviceNickCM {
|
if dc.casemap(mask) == serviceNickCM {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_WHOISUSER,
|
Command: irc.RPL_WHOISUSER,
|
||||||
Params: []string{dc.nick, serviceNick, servicePrefix.User, servicePrefix.Host, "*", serviceRealname},
|
Params: []string{dc.nick, serviceNick, servicePrefix.User, servicePrefix.Host, "*", serviceRealname},
|
||||||
})
|
})
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_WHOISSERVER,
|
Command: irc.RPL_WHOISSERVER,
|
||||||
Params: []string{dc.nick, serviceNick, dc.srv.Config().Hostname, "soju"},
|
Params: []string{dc.nick, serviceNick, dc.srv.Config().Hostname, "soju"},
|
||||||
})
|
})
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_WHOISOPERATOR,
|
Command: irc.RPL_WHOISOPERATOR,
|
||||||
Params: []string{dc.nick, serviceNick, "is the bouncer service"},
|
Params: []string{dc.nick, serviceNick, "is the bouncer service"},
|
||||||
})
|
})
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: xirc.RPL_WHOISACCOUNT,
|
Command: xirc.RPL_WHOISACCOUNT,
|
||||||
Params: []string{dc.nick, serviceNick, serviceNick, "is logged in as"},
|
Params: []string{dc.nick, serviceNick, serviceNick, "is logged in as"},
|
||||||
})
|
})
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: xirc.RPL_WHOISBOT,
|
Command: xirc.RPL_WHOISBOT,
|
||||||
Params: []string{dc.nick, serviceNick, "is a bot"},
|
Params: []string{dc.nick, serviceNick, "is a bot"},
|
||||||
})
|
})
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_ENDOFWHOIS,
|
Command: irc.RPL_ENDOFWHOIS,
|
||||||
Params: []string{dc.nick, serviceNick, "End of /WHOIS list"},
|
Params: []string{dc.nick, serviceNick, "End of /WHOIS list"},
|
||||||
})
|
})
|
||||||
|
@ -2381,7 +2344,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
// hostname, broadcast the message to all bouncer users.
|
// hostname, broadcast the message to all bouncer users.
|
||||||
if !dc.user.Admin {
|
if !dc.user.Admin {
|
||||||
return ircError{&irc.Message{
|
return ircError{&irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_BADMASK,
|
Command: irc.ERR_BADMASK,
|
||||||
Params: []string{dc.nick, name, "Permission denied to broadcast message to all bouncer users"},
|
Params: []string{dc.nick, name, "Permission denied to broadcast message to all bouncer users"},
|
||||||
}}
|
}}
|
||||||
|
@ -2518,7 +2480,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
|
|
||||||
if uc.saslClient != nil {
|
if uc.saslClient != nil {
|
||||||
dc.endSASL(ctx, &irc.Message{
|
dc.endSASL(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{dc.nick, "Another authentication attempt is already in progress"},
|
Params: []string{dc.nick, "Another authentication attempt is already in progress"},
|
||||||
})
|
})
|
||||||
|
@ -2545,7 +2506,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dc.logger.Printf("failed to clear SASL credentials")
|
dc.logger.Printf("failed to clear SASL credentials")
|
||||||
dc.endSASL(ctx, &irc.Message{
|
dc.endSASL(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{dc.nick, "Internal server error"},
|
Params: []string{dc.nick, "Internal server error"},
|
||||||
})
|
})
|
||||||
|
@ -2555,7 +2515,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
dc.endSASL(ctx, nil)
|
dc.endSASL(ctx, nil)
|
||||||
default:
|
default:
|
||||||
dc.endSASL(ctx, &irc.Message{
|
dc.endSASL(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_SASLFAIL,
|
Command: irc.ERR_SASLFAIL,
|
||||||
Params: []string{dc.nick, "Unsupported SASL authentication mechanism"},
|
Params: []string{dc.nick, "Unsupported SASL authentication mechanism"},
|
||||||
})
|
})
|
||||||
|
@ -2584,7 +2543,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
dc.away = nil
|
dc.away = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SendMessage(ctx, generateAwayReply(dc.away != nil, dc.srv.prefix()))
|
dc.SendMessage(ctx, generateAwayReply(dc.away != nil))
|
||||||
|
|
||||||
uc := dc.upstream()
|
uc := dc.upstream()
|
||||||
if uc != nil {
|
if uc != nil {
|
||||||
|
@ -2636,7 +2595,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
// Hard limit, just to avoid having downstreams fill our map
|
// Hard limit, just to avoid having downstreams fill our map
|
||||||
if dc.monitored.Len() >= 1000 {
|
if dc.monitored.Len() >= 1000 {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_MONLISTFULL,
|
Command: irc.ERR_MONLISTFULL,
|
||||||
Params: []string{dc.nick, "1000", target, "Bouncer monitor list is full"},
|
Params: []string{dc.nick, "1000", target, "Bouncer monitor list is full"},
|
||||||
})
|
})
|
||||||
|
@ -2648,7 +2606,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
if uc.network.casemap(target) == serviceNickCM {
|
if uc.network.casemap(target) == serviceNickCM {
|
||||||
// BouncerServ is never tired
|
// BouncerServ is never tired
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_MONONLINE,
|
Command: irc.RPL_MONONLINE,
|
||||||
Params: []string{dc.nick, target},
|
Params: []string{dc.nick, target},
|
||||||
})
|
})
|
||||||
|
@ -2662,7 +2619,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: cmd,
|
Command: cmd,
|
||||||
Params: []string{dc.nick, target},
|
Params: []string{dc.nick, target},
|
||||||
})
|
})
|
||||||
|
@ -2679,13 +2635,11 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
// TODO: be less lazy and pack the list
|
// TODO: be less lazy and pack the list
|
||||||
dc.monitored.ForEach(func(name string, _ struct{}) {
|
dc.monitored.ForEach(func(name string, _ struct{}) {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_MONLIST,
|
Command: irc.RPL_MONLIST,
|
||||||
Params: []string{dc.nick, name},
|
Params: []string{dc.nick, name},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_ENDOFMONLIST,
|
Command: irc.RPL_ENDOFMONLIST,
|
||||||
Params: []string{dc.nick, "End of MONITOR list"},
|
Params: []string{dc.nick, "End of MONITOR list"},
|
||||||
})
|
})
|
||||||
|
@ -2702,7 +2656,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: cmd,
|
Command: cmd,
|
||||||
Params: []string{dc.nick, target},
|
Params: []string{dc.nick, target},
|
||||||
})
|
})
|
||||||
|
@ -2832,7 +2785,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
|
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Tags: irc.Tags{"batch": batchRef},
|
Tags: irc.Tags{"batch": batchRef},
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "CHATHISTORY",
|
Command: "CHATHISTORY",
|
||||||
Params: []string{"TARGETS", target.Name, xirc.FormatServerTime(target.LatestMessage)},
|
Params: []string{"TARGETS", target.Name, xirc.FormatServerTime(target.LatestMessage)},
|
||||||
})
|
})
|
||||||
|
@ -3064,7 +3016,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
attrs := getNetworkAttrs(network)
|
attrs := getNetworkAttrs(network)
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Tags: irc.Tags{"batch": batchRef},
|
Tags: irc.Tags{"batch": batchRef},
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "BOUNCER",
|
Command: "BOUNCER",
|
||||||
Params: []string{"NETWORK", idStr, attrs.String()},
|
Params: []string{"NETWORK", idStr, attrs.String()},
|
||||||
})
|
})
|
||||||
|
@ -3099,7 +3050,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "BOUNCER",
|
Command: "BOUNCER",
|
||||||
Params: []string{"ADDNETWORK", fmt.Sprintf("%v", network.ID)},
|
Params: []string{"ADDNETWORK", fmt.Sprintf("%v", network.ID)},
|
||||||
})
|
})
|
||||||
|
@ -3143,7 +3093,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "BOUNCER",
|
Command: "BOUNCER",
|
||||||
Params: []string{"CHANGENETWORK", idStr},
|
Params: []string{"CHANGENETWORK", idStr},
|
||||||
})
|
})
|
||||||
|
@ -3170,7 +3119,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "BOUNCER",
|
Command: "BOUNCER",
|
||||||
Params: []string{"DELNETWORK", idStr},
|
Params: []string{"DELNETWORK", idStr},
|
||||||
})
|
})
|
||||||
|
@ -3274,7 +3222,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "WEBPUSH",
|
Command: "WEBPUSH",
|
||||||
Params: []string{"REGISTER", endpoint},
|
Params: []string{"REGISTER", endpoint},
|
||||||
})
|
})
|
||||||
|
@ -3296,7 +3243,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
oldSub := findWebPushSubscription(subs, endpoint)
|
oldSub := findWebPushSubscription(subs, endpoint)
|
||||||
if oldSub == nil {
|
if oldSub == nil {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "WEBPUSH",
|
Command: "WEBPUSH",
|
||||||
Params: []string{"UNREGISTER", endpoint},
|
Params: []string{"UNREGISTER", endpoint},
|
||||||
})
|
})
|
||||||
|
@ -3312,7 +3258,6 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "WEBPUSH",
|
Command: "WEBPUSH",
|
||||||
Params: []string{"UNREGISTER", endpoint},
|
Params: []string{"UNREGISTER", endpoint},
|
||||||
})
|
})
|
||||||
|
@ -3440,21 +3385,18 @@ func forwardChannel(ctx context.Context, dc *downstreamConn, ch *upstreamChannel
|
||||||
func sendTopic(ctx context.Context, dc *downstreamConn, ch *upstreamChannel) {
|
func sendTopic(ctx context.Context, dc *downstreamConn, ch *upstreamChannel) {
|
||||||
if ch.Topic != "" {
|
if ch.Topic != "" {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_TOPIC,
|
Command: irc.RPL_TOPIC,
|
||||||
Params: []string{dc.nick, ch.Name, ch.Topic},
|
Params: []string{dc.nick, ch.Name, ch.Topic},
|
||||||
})
|
})
|
||||||
if ch.TopicWho != nil {
|
if ch.TopicWho != nil {
|
||||||
topicTime := strconv.FormatInt(ch.TopicTime.Unix(), 10)
|
topicTime := strconv.FormatInt(ch.TopicTime.Unix(), 10)
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: xirc.RPL_TOPICWHOTIME,
|
Command: xirc.RPL_TOPICWHOTIME,
|
||||||
Params: []string{dc.nick, ch.Name, ch.TopicWho.String(), topicTime},
|
Params: []string{dc.nick, ch.Name, ch.TopicWho.String(), topicTime},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_NOTOPIC,
|
Command: irc.RPL_NOTOPIC,
|
||||||
Params: []string{dc.nick, ch.Name, "No topic is set"},
|
Params: []string{dc.nick, ch.Name, "No topic is set"},
|
||||||
})
|
})
|
||||||
|
@ -3468,7 +3410,7 @@ func sendNames(ctx context.Context, dc *downstreamConn, ch *upstreamChannel) {
|
||||||
members = append(members, s)
|
members = append(members, s)
|
||||||
})
|
})
|
||||||
|
|
||||||
msgs := xirc.GenerateNamesReply(dc.srv.prefix(), ch.Name, ch.Status, members)
|
msgs := xirc.GenerateNamesReply(ch.Name, ch.Status, members)
|
||||||
for _, msg := range msgs {
|
for _, msg := range msgs {
|
||||||
dc.SendMessage(ctx, msg)
|
dc.SendMessage(ctx, msg)
|
||||||
}
|
}
|
||||||
|
|
24
go.mod
24
go.mod
|
@ -12,34 +12,34 @@ require (
|
||||||
github.com/mattn/go-sqlite3 v1.14.22
|
github.com/mattn/go-sqlite3 v1.14.22
|
||||||
github.com/msteinert/pam/v2 v2.0.0
|
github.com/msteinert/pam/v2 v2.0.0
|
||||||
github.com/pires/go-proxyproto v0.7.0
|
github.com/pires/go-proxyproto v0.7.0
|
||||||
github.com/prometheus/client_golang v1.18.0
|
github.com/prometheus/client_golang v1.19.1
|
||||||
golang.org/x/crypto v0.21.0
|
golang.org/x/crypto v0.23.0
|
||||||
golang.org/x/time v0.5.0
|
golang.org/x/time v0.5.0
|
||||||
gopkg.in/irc.v4 v4.0.0
|
gopkg.in/irc.v4 v4.0.0
|
||||||
modernc.org/sqlite v1.29.5
|
modernc.org/sqlite v1.29.10
|
||||||
nhooyr.io/websocket v1.8.10
|
nhooyr.io/websocket v1.8.11
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||||
github.com/prometheus/client_model v0.6.0 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.47.0 // indirect
|
github.com/prometheus/common v0.53.0 // indirect
|
||||||
github.com/prometheus/procfs v0.13.0 // indirect
|
github.com/prometheus/procfs v0.13.0 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
golang.org/x/sys v0.18.0 // indirect
|
golang.org/x/sys v0.20.0 // indirect
|
||||||
golang.org/x/term v0.18.0 // indirect
|
golang.org/x/term v0.20.0 // indirect
|
||||||
google.golang.org/protobuf v1.33.0 // indirect
|
google.golang.org/protobuf v1.34.1 // indirect
|
||||||
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
|
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
|
||||||
modernc.org/libc v1.41.0 // indirect
|
modernc.org/libc v1.50.8 // indirect
|
||||||
modernc.org/mathutil v1.6.0 // indirect
|
modernc.org/mathutil v1.6.0 // indirect
|
||||||
modernc.org/memory v1.7.2 // indirect
|
modernc.org/memory v1.8.0 // indirect
|
||||||
modernc.org/strutil v1.2.0 // indirect
|
modernc.org/strutil v1.2.0 // indirect
|
||||||
modernc.org/token v1.1.0 // indirect
|
modernc.org/token v1.1.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
59
go.sum
59
go.sum
|
@ -9,8 +9,8 @@ github.com/SherClockHolmes/webpush-go v1.3.0 h1:CAu3FvEE9QS4drc3iKNgpBWFfGqNthKl
|
||||||
github.com/SherClockHolmes/webpush-go v1.3.0/go.mod h1:AxRHmJuYwKGG1PVgYzToik1lphQvDnqFYDqimHvwhIw=
|
github.com/SherClockHolmes/webpush-go v1.3.0/go.mod h1:AxRHmJuYwKGG1PVgYzToik1lphQvDnqFYDqimHvwhIw=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -21,7 +21,7 @@ github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTe
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||||
|
@ -40,12 +40,12 @@ github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwy
|
||||||
github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4=
|
github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
|
||||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
|
||||||
github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/common v0.47.0 h1:p5Cz0FNHo7SnWOmWmoRozVcjEp0bIVU8cV7OShpjL1k=
|
github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE=
|
||||||
github.com/prometheus/common v0.47.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
|
||||||
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
|
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
|
||||||
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
|
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
|
@ -61,11 +61,11 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
@ -82,14 +82,14 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
|
||||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
@ -102,10 +102,10 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/irc.v4 v4.0.0 h1:5jsLkU2Tg+R2nGNqmkGCrciasyi4kNkDXhyZD+C31yY=
|
gopkg.in/irc.v4 v4.0.0 h1:5jsLkU2Tg+R2nGNqmkGCrciasyi4kNkDXhyZD+C31yY=
|
||||||
gopkg.in/irc.v4 v4.0.0/go.mod h1:BfjDz9MmuWW6OZY7iq4naOhudO8+QQCdO4Ko18jcsRE=
|
gopkg.in/irc.v4 v4.0.0/go.mod h1:BfjDz9MmuWW6OZY7iq4naOhudO8+QQCdO4Ko18jcsRE=
|
||||||
|
@ -114,20 +114,25 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
modernc.org/cc/v4 v4.21.2 h1:dycHFB/jDc3IyacKipCNSDrjIC0Lm1hyoWOZTRR20Lk=
|
||||||
|
modernc.org/ccgo/v4 v4.17.7 h1:+MG+Np7uYtsuPvtoH3KtZ1+pqNiJAOqqqVIxggE1iIo=
|
||||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
||||||
|
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
|
||||||
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b h1:BnN1t+pb1cy61zbvSUV7SeI0PwosMhlAEi/vBY4qxp8=
|
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b h1:BnN1t+pb1cy61zbvSUV7SeI0PwosMhlAEi/vBY4qxp8=
|
||||||
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
|
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
|
||||||
modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk=
|
modernc.org/libc v1.50.8 h1:bL2wUMEguwacIaF7q3Hn8WmjNn/yphgVFIE6xyLdN9c=
|
||||||
modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY=
|
modernc.org/libc v1.50.8/go.mod h1:8lr2m1THY5Z3ikGyUc3JhLEQg1oaIBz/AQixw8/eksQ=
|
||||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||||
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
|
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
||||||
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
|
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
||||||
modernc.org/sqlite v1.29.5 h1:8l/SQKAjDtZFo9lkJLdk8g9JEOeYRG4/ghStDCCTiTE=
|
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||||
modernc.org/sqlite v1.29.5/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U=
|
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
||||||
|
modernc.org/sqlite v1.29.10 h1:3u93dz83myFnMilBGCOLbr+HjklS6+5rJLx4q86RDAg=
|
||||||
|
modernc.org/sqlite v1.29.10/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA=
|
||||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
||||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
||||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||||
nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q=
|
nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0=
|
||||||
nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
|
nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
|
||||||
|
|
3
irc.go
3
irc.go
|
@ -299,7 +299,7 @@ func isNumeric(cmd string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateAwayReply(away bool, prefix *irc.Prefix) *irc.Message {
|
func generateAwayReply(away bool) *irc.Message {
|
||||||
cmd := irc.RPL_NOWAWAY
|
cmd := irc.RPL_NOWAWAY
|
||||||
desc := "You have been marked as being away"
|
desc := "You have been marked as being away"
|
||||||
if !away {
|
if !away {
|
||||||
|
@ -307,7 +307,6 @@ func generateAwayReply(away bool, prefix *irc.Prefix) *irc.Message {
|
||||||
desc = "You are no longer marked as being away"
|
desc = "You are no longer marked as being away"
|
||||||
}
|
}
|
||||||
return &irc.Message{
|
return &irc.Message{
|
||||||
Prefix: prefix,
|
|
||||||
Command: cmd,
|
Command: cmd,
|
||||||
Params: []string{"*", desc},
|
Params: []string{"*", desc},
|
||||||
}
|
}
|
||||||
|
|
18
service.go
18
service.go
|
@ -279,6 +279,7 @@ func init() {
|
||||||
"user": {
|
"user": {
|
||||||
children: serviceCommandSet{
|
children: serviceCommandSet{
|
||||||
"status": {
|
"status": {
|
||||||
|
usage: "[username]",
|
||||||
desc: "show a list of users and their current status",
|
desc: "show a list of users and their current status",
|
||||||
handle: handleUserStatus,
|
handle: handleUserStatus,
|
||||||
admin: true,
|
admin: true,
|
||||||
|
@ -900,16 +901,18 @@ func handleServiceSASLReset(ctx *serviceContext, params []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleUserStatus(ctx *serviceContext, params []string) error {
|
func handleUserStatus(ctx *serviceContext, params []string) error {
|
||||||
if len(params) != 0 {
|
if len(params) > 1 {
|
||||||
return fmt.Errorf("expected no argument")
|
return fmt.Errorf("expected 0 or 1 argument")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit to a small amount of users to avoid sending
|
// Limit to a small amount of users to avoid sending
|
||||||
// thousands of messages on large instances.
|
// thousands of messages on large instances.
|
||||||
users := make([]database.User, 0, 50)
|
users := make([]database.User, 0, 50)
|
||||||
|
var n int
|
||||||
|
|
||||||
|
if len(params) == 0 {
|
||||||
ctx.srv.lock.Lock()
|
ctx.srv.lock.Lock()
|
||||||
n := len(ctx.srv.users)
|
n = len(ctx.srv.users)
|
||||||
for _, user := range ctx.srv.users {
|
for _, user := range ctx.srv.users {
|
||||||
if len(users) == cap(users) {
|
if len(users) == cap(users) {
|
||||||
break
|
break
|
||||||
|
@ -917,6 +920,15 @@ func handleUserStatus(ctx *serviceContext, params []string) error {
|
||||||
users = append(users, user.User)
|
users = append(users, user.User)
|
||||||
}
|
}
|
||||||
ctx.srv.lock.Unlock()
|
ctx.srv.lock.Unlock()
|
||||||
|
} else {
|
||||||
|
username := params[0]
|
||||||
|
u := ctx.srv.getUser(username)
|
||||||
|
if u == nil {
|
||||||
|
return fmt.Errorf("unknown username %q", username)
|
||||||
|
}
|
||||||
|
users = append(users, u.User)
|
||||||
|
n = 1
|
||||||
|
}
|
||||||
|
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
var attrs []string
|
var attrs []string
|
||||||
|
|
|
@ -461,7 +461,6 @@ func (uc *upstreamConn) abortPendingCommands() {
|
||||||
switch pendingCmd.msg.Command {
|
switch pendingCmd.msg.Command {
|
||||||
case "LIST":
|
case "LIST":
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_LISTEND,
|
Command: irc.RPL_LISTEND,
|
||||||
Params: []string{dc.nick, "Command aborted"},
|
Params: []string{dc.nick, "Command aborted"},
|
||||||
})
|
})
|
||||||
|
@ -471,26 +470,22 @@ func (uc *upstreamConn) abortPendingCommands() {
|
||||||
mask = pendingCmd.msg.Params[0]
|
mask = pendingCmd.msg.Params[0]
|
||||||
}
|
}
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_ENDOFWHO,
|
Command: irc.RPL_ENDOFWHO,
|
||||||
Params: []string{dc.nick, mask, "Command aborted"},
|
Params: []string{dc.nick, mask, "Command aborted"},
|
||||||
})
|
})
|
||||||
case "WHOIS":
|
case "WHOIS":
|
||||||
nick := pendingCmd.msg.Params[len(pendingCmd.msg.Params)-1]
|
nick := pendingCmd.msg.Params[len(pendingCmd.msg.Params)-1]
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.RPL_ENDOFWHOIS,
|
Command: irc.RPL_ENDOFWHOIS,
|
||||||
Params: []string{dc.nick, nick, "Command aborted"},
|
Params: []string{dc.nick, nick, "Command aborted"},
|
||||||
})
|
})
|
||||||
case "AUTHENTICATE":
|
case "AUTHENTICATE":
|
||||||
dc.endSASL(ctx, &irc.Message{
|
dc.endSASL(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: irc.ERR_SASLABORTED,
|
Command: irc.ERR_SASLABORTED,
|
||||||
Params: []string{dc.nick, "SASL authentication aborted"},
|
Params: []string{dc.nick, "SASL authentication aborted"},
|
||||||
})
|
})
|
||||||
case "REGISTER", "VERIFY":
|
case "REGISTER", "VERIFY":
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "FAIL",
|
Command: "FAIL",
|
||||||
Params: []string{pendingCmd.msg.Command, "TEMPORARILY_UNAVAILABLE", pendingCmd.msg.Params[0], "Command aborted"},
|
Params: []string{pendingCmd.msg.Command, "TEMPORARILY_UNAVAILABLE", pendingCmd.msg.Params[0], "Command aborted"},
|
||||||
})
|
})
|
||||||
|
@ -1017,7 +1012,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
|
||||||
uc.updateMonitor()
|
uc.updateMonitor()
|
||||||
|
|
||||||
uc.forEachDownstream(func(dc *downstreamConn) {
|
uc.forEachDownstream(func(dc *downstreamConn) {
|
||||||
msgs := xirc.GenerateIsupport(dc.srv.prefix(), downstreamIsupport)
|
msgs := xirc.GenerateIsupport(downstreamIsupport)
|
||||||
for _, msg := range msgs {
|
for _, msg := range msgs {
|
||||||
dc.SendMessage(ctx, msg)
|
dc.SendMessage(ctx, msg)
|
||||||
}
|
}
|
||||||
|
@ -1685,7 +1680,6 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
|
||||||
prefix := irc.ParsePrefix(target)
|
prefix := irc.ParsePrefix(target)
|
||||||
if dc.monitored.Has(prefix.Name) {
|
if dc.monitored.Has(prefix.Name) {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: msg.Command,
|
Command: msg.Command,
|
||||||
Params: []string{dc.nick, target},
|
Params: []string{dc.nick, target},
|
||||||
})
|
})
|
||||||
|
@ -1703,7 +1697,6 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
|
||||||
for _, target := range targets {
|
for _, target := range targets {
|
||||||
if dc.monitored.Has(target) {
|
if dc.monitored.Has(target) {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: msg.Command,
|
Command: msg.Command,
|
||||||
Params: []string{dc.nick, limit, target},
|
Params: []string{dc.nick, limit, target},
|
||||||
})
|
})
|
||||||
|
|
2
user.go
2
user.go
|
@ -926,7 +926,6 @@ func (u *user) notifyBouncerNetworkState(netID int64, attrs irc.Tags) {
|
||||||
for _, dc := range u.downstreamConns {
|
for _, dc := range u.downstreamConns {
|
||||||
if dc.caps.IsEnabled("soju.im/bouncer-networks-notify") {
|
if dc.caps.IsEnabled("soju.im/bouncer-networks-notify") {
|
||||||
dc.SendMessage(context.TODO(), &irc.Message{
|
dc.SendMessage(context.TODO(), &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "BOUNCER",
|
Command: "BOUNCER",
|
||||||
Params: []string{"NETWORK", netIDStr, attrs.String()},
|
Params: []string{"NETWORK", netIDStr, attrs.String()},
|
||||||
})
|
})
|
||||||
|
@ -1130,7 +1129,6 @@ func (u *user) deleteNetwork(ctx context.Context, id int64) error {
|
||||||
for _, dc := range u.downstreamConns {
|
for _, dc := range u.downstreamConns {
|
||||||
if dc.caps.IsEnabled("soju.im/bouncer-networks-notify") {
|
if dc.caps.IsEnabled("soju.im/bouncer-networks-notify") {
|
||||||
dc.SendMessage(ctx, &irc.Message{
|
dc.SendMessage(ctx, &irc.Message{
|
||||||
Prefix: dc.srv.prefix(),
|
|
||||||
Command: "BOUNCER",
|
Command: "BOUNCER",
|
||||||
Params: []string{"NETWORK", idStr, "*"},
|
Params: []string{"NETWORK", idStr, "*"},
|
||||||
})
|
})
|
||||||
|
|
|
@ -82,7 +82,7 @@ func (js *joinSorter) Swap(i, j int) {
|
||||||
js.keys[i], js.keys[j] = js.keys[j], js.keys[i]
|
js.keys[i], js.keys[j] = js.keys[j], js.keys[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateIsupport(prefix *irc.Prefix, tokens []string) []*irc.Message {
|
func GenerateIsupport(tokens []string) []*irc.Message {
|
||||||
maxTokens := maxMessageParams - 2 // 2 reserved params: nick + text
|
maxTokens := maxMessageParams - 2 // 2 reserved params: nick + text
|
||||||
|
|
||||||
// TODO: take into account maxMessageLength as well
|
// TODO: take into account maxMessageLength as well
|
||||||
|
@ -103,7 +103,6 @@ func GenerateIsupport(prefix *irc.Prefix, tokens []string) []*irc.Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
msgs = append(msgs, &irc.Message{
|
msgs = append(msgs, &irc.Message{
|
||||||
Prefix: prefix,
|
|
||||||
Command: irc.RPL_ISUPPORT,
|
Command: irc.RPL_ISUPPORT,
|
||||||
Params: append(append([]string{"*"}, encodedTokens...), "are supported"),
|
Params: append(append([]string{"*"}, encodedTokens...), "are supported"),
|
||||||
})
|
})
|
||||||
|
@ -114,24 +113,21 @@ func GenerateIsupport(prefix *irc.Prefix, tokens []string) []*irc.Message {
|
||||||
|
|
||||||
var isupportEncoder = strings.NewReplacer(" ", "\\x20", "\\", "\\x5C")
|
var isupportEncoder = strings.NewReplacer(" ", "\\x20", "\\", "\\x5C")
|
||||||
|
|
||||||
func GenerateMOTD(prefix *irc.Prefix, motd string) []*irc.Message {
|
func GenerateMOTD(motd string) []*irc.Message {
|
||||||
var msgs []*irc.Message
|
var msgs []*irc.Message
|
||||||
msgs = append(msgs, &irc.Message{
|
msgs = append(msgs, &irc.Message{
|
||||||
Prefix: prefix,
|
|
||||||
Command: irc.RPL_MOTDSTART,
|
Command: irc.RPL_MOTDSTART,
|
||||||
Params: []string{"*", fmt.Sprintf("- Message of the Day -")},
|
Params: []string{"*", fmt.Sprintf("- Message of the Day -")},
|
||||||
})
|
})
|
||||||
|
|
||||||
for _, l := range strings.Split(motd, "\n") {
|
for _, l := range strings.Split(motd, "\n") {
|
||||||
msgs = append(msgs, &irc.Message{
|
msgs = append(msgs, &irc.Message{
|
||||||
Prefix: prefix,
|
|
||||||
Command: irc.RPL_MOTD,
|
Command: irc.RPL_MOTD,
|
||||||
Params: []string{"*", l},
|
Params: []string{"*", l},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
msgs = append(msgs, &irc.Message{
|
msgs = append(msgs, &irc.Message{
|
||||||
Prefix: prefix,
|
|
||||||
Command: irc.RPL_ENDOFMOTD,
|
Command: irc.RPL_ENDOFMOTD,
|
||||||
Params: []string{"*", "End of /MOTD command."},
|
Params: []string{"*", "End of /MOTD command."},
|
||||||
})
|
})
|
||||||
|
@ -169,9 +165,8 @@ func GenerateMonitor(subcmd string, targets []string) []*irc.Message {
|
||||||
return msgs
|
return msgs
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateNamesReply(prefix *irc.Prefix, channel string, status ChannelStatus, members []string) []*irc.Message {
|
func GenerateNamesReply(channel string, status ChannelStatus, members []string) []*irc.Message {
|
||||||
emptyNameReply := irc.Message{
|
emptyNameReply := irc.Message{
|
||||||
Prefix: prefix,
|
|
||||||
Command: irc.RPL_NAMREPLY,
|
Command: irc.RPL_NAMREPLY,
|
||||||
Params: []string{"*", string(status), channel, ""},
|
Params: []string{"*", string(status), channel, ""},
|
||||||
}
|
}
|
||||||
|
@ -184,7 +179,6 @@ func GenerateNamesReply(prefix *irc.Prefix, channel string, status ChannelStatus
|
||||||
if buf.Len() != 0 && n > maxLength {
|
if buf.Len() != 0 && n > maxLength {
|
||||||
// There's not enough space for the next space + nick
|
// There's not enough space for the next space + nick
|
||||||
msgs = append(msgs, &irc.Message{
|
msgs = append(msgs, &irc.Message{
|
||||||
Prefix: prefix,
|
|
||||||
Command: irc.RPL_NAMREPLY,
|
Command: irc.RPL_NAMREPLY,
|
||||||
Params: []string{"*", string(status), channel, buf.String()},
|
Params: []string{"*", string(status), channel, buf.String()},
|
||||||
})
|
})
|
||||||
|
@ -199,14 +193,12 @@ func GenerateNamesReply(prefix *irc.Prefix, channel string, status ChannelStatus
|
||||||
|
|
||||||
if buf.Len() != 0 {
|
if buf.Len() != 0 {
|
||||||
msgs = append(msgs, &irc.Message{
|
msgs = append(msgs, &irc.Message{
|
||||||
Prefix: prefix,
|
|
||||||
Command: irc.RPL_NAMREPLY,
|
Command: irc.RPL_NAMREPLY,
|
||||||
Params: []string{"*", string(status), channel, buf.String()},
|
Params: []string{"*", string(status), channel, buf.String()},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
msgs = append(msgs, &irc.Message{
|
msgs = append(msgs, &irc.Message{
|
||||||
Prefix: prefix,
|
|
||||||
Command: irc.RPL_ENDOFNAMES,
|
Command: irc.RPL_ENDOFNAMES,
|
||||||
Params: []string{"*", channel, "End of /NAMES list"},
|
Params: []string{"*", channel, "End of /NAMES list"},
|
||||||
})
|
})
|
||||||
|
|
|
@ -93,7 +93,7 @@ func (info *WHOXInfo) set(k byte, v string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateWHOXReply(prefix *irc.Prefix, fields string, info *WHOXInfo) *irc.Message {
|
func GenerateWHOXReply(fields string, info *WHOXInfo) *irc.Message {
|
||||||
if fields == "" {
|
if fields == "" {
|
||||||
hostname := info.Hostname
|
hostname := info.Hostname
|
||||||
if strings.HasPrefix(info.Hostname, ":") {
|
if strings.HasPrefix(info.Hostname, ":") {
|
||||||
|
@ -109,7 +109,6 @@ func GenerateWHOXReply(prefix *irc.Prefix, fields string, info *WHOXInfo) *irc.M
|
||||||
}
|
}
|
||||||
|
|
||||||
return &irc.Message{
|
return &irc.Message{
|
||||||
Prefix: prefix,
|
|
||||||
Command: irc.RPL_WHOREPLY,
|
Command: irc.RPL_WHOREPLY,
|
||||||
Params: []string{"*", channel, info.Username, hostname, info.Server, info.Nickname, info.Flags, "0 " + info.Realname},
|
Params: []string{"*", channel, info.Username, hostname, info.Server, info.Nickname, info.Flags, "0 " + info.Realname},
|
||||||
}
|
}
|
||||||
|
@ -129,7 +128,6 @@ func GenerateWHOXReply(prefix *irc.Prefix, fields string, info *WHOXInfo) *irc.M
|
||||||
}
|
}
|
||||||
|
|
||||||
return &irc.Message{
|
return &irc.Message{
|
||||||
Prefix: prefix,
|
|
||||||
Command: RPL_WHOSPCRPL,
|
Command: RPL_WHOSPCRPL,
|
||||||
Params: append([]string{"*"}, values...),
|
Params: append([]string{"*"}, values...),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue