Add KICK support

Downstream and upstream message handling are slightly different because
downstreams can send KICK messages with multiple channels or users,
while upstreams can only send KICK messages with one channel and one
user (according to the RFC).

git-svn-id: file:///srv/svn/repo/suika/trunk@159 f0ae65fe-ee39-954e-97ec-027ff2717ef4
This commit is contained in:
delthas 2020-03-25 23:15:26 +00:00
parent 8a4a0173a4
commit 3318e3fbfe
2 changed files with 93 additions and 0 deletions

View File

@ -903,6 +903,62 @@ func (dc *downstreamConn) handleMessageRegistered(msg *irc.Message) error {
dc.logger.Printf("failed to delete channel %q in DB: %v", upstreamName, err)
}
}
case "KICK":
var channelStr, userStr string
if err := parseMessageParams(msg, &channelStr, &userStr); err != nil {
return err
}
channels := strings.Split(channelStr, ",")
users := strings.Split(userStr, ",")
var reason string
if len(msg.Params) > 2 {
reason = msg.Params[2]
}
if len(channels) != 1 && len(channels) != len(users) {
return ircError{&irc.Message{
Command: irc.ERR_BADCHANMASK,
Params: []string{dc.nick, channelStr, "Bad channel mask"},
}}
}
for i, user := range users {
var channel string
if len(channels) == 1 {
channel = channels[0]
} else {
channel = channels[i]
}
ucChannel, upstreamChannel, err := dc.unmarshalEntity(channel)
if err != nil {
return err
}
ucUser, upstreamUser, err := dc.unmarshalEntity(user)
if err != nil {
return err
}
if ucChannel != ucUser {
return ircError{&irc.Message{
Command: irc.ERR_USERNOTINCHANNEL,
Params: []string{dc.nick, user, channel, "They aren't on that channel"},
}}
}
uc := ucChannel
params := []string{upstreamChannel, upstreamUser}
if reason != "" {
params = append(params, reason)
}
uc.SendMessage(&irc.Message{
Command: "KICK",
Params: params,
})
}
case "MODE":
var name string
if err := parseMessageParams(msg, &name); err != nil {

View File

@ -582,6 +582,43 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
})
})
}
case "KICK":
if msg.Prefix == nil {
return fmt.Errorf("expected a prefix")
}
var channel, user string
if err := parseMessageParams(msg, &channel, &user); err != nil {
return err
}
var reason string
if len(msg.Params) > 2 {
reason = msg.Params[1]
}
if user == uc.nick {
uc.logger.Printf("kicked from channel %q by %s", channel, msg.Prefix.Name)
delete(uc.channels, channel)
} else {
ch, err := uc.getChannel(channel)
if err != nil {
return err
}
delete(ch.Members, user)
}
uc.forEachDownstream(func(dc *downstreamConn) {
params := []string{dc.marshalChannel(uc, channel), dc.marshalNick(uc, user)}
if reason != "" {
params = append(params, reason)
}
dc.SendMessage(&irc.Message{
Prefix: dc.marshalUserPrefix(uc, msg.Prefix),
Command: "KICK",
Params: params,
})
})
case "QUIT":
if msg.Prefix == nil {
return fmt.Errorf("expected a prefix")