Add parseMessageParams helper

This commit is contained in:
Simon Ser 2020-02-07 12:36:02 +01:00
parent 6d03af8243
commit 96653499dc
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
3 changed files with 61 additions and 46 deletions

View file

@ -156,16 +156,15 @@ func (c *downstreamConn) handleMessage(msg *irc.Message) error {
func (c *downstreamConn) handleMessageUnregistered(msg *irc.Message) error { func (c *downstreamConn) handleMessageUnregistered(msg *irc.Message) error {
switch msg.Command { switch msg.Command {
case "NICK": case "NICK":
if len(msg.Params) != 1 { if err := parseMessageParams(msg, &c.nick); err != nil {
return newNeedMoreParamsError(msg.Command) return err
} }
c.nick = msg.Params[0]
case "USER": case "USER":
if len(msg.Params) != 4 { var username string
return newNeedMoreParamsError(msg.Command) if err := parseMessageParams(msg, &username, nil, nil, &c.realname); err != nil {
return err
} }
c.username = "~" + msg.Params[0] c.username = "~" + username
c.realname = msg.Params[3]
default: default:
c.logger.Printf("unhandled message: %v", msg) c.logger.Printf("unhandled message: %v", msg)
return newUnknownCommandError(msg.Command) return newUnknownCommandError(msg.Command)

14
irc.go
View file

@ -3,6 +3,8 @@ package jounce
import ( import (
"fmt" "fmt"
"strings" "strings"
"gopkg.in/irc.v3"
) )
const ( const (
@ -90,3 +92,15 @@ func parseMembershipPrefix(s string) (prefix membership, nick string) {
return 0, s return 0, s
} }
} }
func parseMessageParams(msg *irc.Message, out ...*string) error {
if len(msg.Params) < len(out) {
return newNeedMoreParamsError(msg.Command)
}
for i := range out {
if out[i] != nil {
*out[i] = msg.Params[i]
}
}
return nil
}

View file

@ -106,11 +106,10 @@ func (c *upstreamConn) handleMessage(msg *irc.Message) error {
} }
return nil return nil
case "MODE": case "MODE":
if len(msg.Params) < 2 { var name, modeStr string
return newNeedMoreParamsError(msg.Command) if err := parseMessageParams(msg, &name, &modeStr); err != nil {
return err
} }
name := msg.Params[0]
modeStr := msg.Params[1]
if name == msg.Prefix.Name { // user mode change if name == msg.Prefix.Name { // user mode change
if name != c.nick { if name != c.nick {
@ -143,20 +142,17 @@ func (c *upstreamConn) handleMessage(msg *irc.Message) error {
} }
} }
case irc.RPL_MYINFO: case irc.RPL_MYINFO:
if len(msg.Params) < 5 { if err := parseMessageParams(msg, nil, &c.serverName, nil, &c.availableUserModes, &c.availableChannelModes); err != nil {
return newNeedMoreParamsError(msg.Command) return err
} }
c.serverName = msg.Params[1]
c.availableUserModes = msg.Params[3]
c.availableChannelModes = msg.Params[4]
if len(msg.Params) > 5 { if len(msg.Params) > 5 {
c.channelModesWithParam = msg.Params[5] c.channelModesWithParam = msg.Params[5]
} }
case "NICK": case "NICK":
if len(msg.Params) < 1 { var newNick string
return newNeedMoreParamsError(msg.Command) if err := parseMessageParams(msg, &newNick); err != nil {
return err
} }
newNick := msg.Params[0]
if msg.Prefix.Name == c.nick { if msg.Prefix.Name == c.nick {
c.logger.Printf("changed nick from %q to %q", c.nick, newNick) c.logger.Printf("changed nick from %q to %q", c.nick, newNick)
@ -174,11 +170,12 @@ func (c *upstreamConn) handleMessage(msg *irc.Message) error {
dc.messages <- msg dc.messages <- msg
}) })
case "JOIN": case "JOIN":
if len(msg.Params) < 1 { var channels string
return newNeedMoreParamsError(msg.Command) if err := parseMessageParams(msg, &channels); err != nil {
return err
} }
for _, ch := range strings.Split(msg.Params[0], ",") { for _, ch := range strings.Split(channels, ",") {
if msg.Prefix.Name == c.nick { if msg.Prefix.Name == c.nick {
c.logger.Printf("joined channel %q", ch) c.logger.Printf("joined channel %q", ch)
c.channels[ch] = &upstreamChannel{ c.channels[ch] = &upstreamChannel{
@ -198,11 +195,12 @@ func (c *upstreamConn) handleMessage(msg *irc.Message) error {
dc.messages <- msg dc.messages <- msg
}) })
case "PART": case "PART":
if len(msg.Params) < 1 { var channels string
return newNeedMoreParamsError(msg.Command) if err := parseMessageParams(msg, &channels); err != nil {
return err
} }
for _, ch := range strings.Split(msg.Params[0], ",") { for _, ch := range strings.Split(channels, ",") {
if msg.Prefix.Name == c.nick { if msg.Prefix.Name == c.nick {
c.logger.Printf("parted channel %q", ch) c.logger.Printf("parted channel %q", ch)
delete(c.channels, ch) delete(c.channels, ch)
@ -219,23 +217,25 @@ func (c *upstreamConn) handleMessage(msg *irc.Message) error {
dc.messages <- msg dc.messages <- msg
}) })
case irc.RPL_TOPIC, irc.RPL_NOTOPIC: case irc.RPL_TOPIC, irc.RPL_NOTOPIC:
if len(msg.Params) < 3 { var name, topic string
return newNeedMoreParamsError(msg.Command) if err := parseMessageParams(msg, nil, &name, &topic); err != nil {
return err
} }
ch, err := c.getChannel(msg.Params[1]) ch, err := c.getChannel(name)
if err != nil { if err != nil {
return err return err
} }
if msg.Command == irc.RPL_TOPIC { if msg.Command == irc.RPL_TOPIC {
ch.Topic = msg.Params[2] ch.Topic = topic
} else { } else {
ch.Topic = "" ch.Topic = ""
} }
case "TOPIC": case "TOPIC":
if len(msg.Params) < 1 { var name string
return newNeedMoreParamsError(msg.Command) if err := parseMessageParams(msg, nil, &name); err != nil {
return err
} }
ch, err := c.getChannel(msg.Params[0]) ch, err := c.getChannel(name)
if err != nil { if err != nil {
return err return err
} }
@ -245,43 +245,46 @@ func (c *upstreamConn) handleMessage(msg *irc.Message) error {
ch.Topic = "" ch.Topic = ""
} }
case rpl_topicwhotime: case rpl_topicwhotime:
if len(msg.Params) < 4 { var name, who, timeStr string
return newNeedMoreParamsError(msg.Command) if err := parseMessageParams(msg, nil, &name, &who, &timeStr); err != nil {
return err
} }
ch, err := c.getChannel(msg.Params[1]) ch, err := c.getChannel(name)
if err != nil { if err != nil {
return err return err
} }
ch.TopicWho = msg.Params[2] ch.TopicWho = who
sec, err := strconv.ParseInt(msg.Params[3], 10, 64) sec, err := strconv.ParseInt(timeStr, 10, 64)
if err != nil { if err != nil {
return fmt.Errorf("failed to parse topic time: %v", err) return fmt.Errorf("failed to parse topic time: %v", err)
} }
ch.TopicTime = time.Unix(sec, 0) ch.TopicTime = time.Unix(sec, 0)
case irc.RPL_NAMREPLY: case irc.RPL_NAMREPLY:
if len(msg.Params) < 4 { var name, statusStr, members string
return newNeedMoreParamsError(msg.Command) if err := parseMessageParams(msg, nil, &statusStr, &name, &members); err != nil {
return err
} }
ch, err := c.getChannel(msg.Params[2]) ch, err := c.getChannel(name)
if err != nil { if err != nil {
return err return err
} }
status, err := parseChannelStatus(msg.Params[1]) status, err := parseChannelStatus(statusStr)
if err != nil { if err != nil {
return err return err
} }
ch.Status = status ch.Status = status
for _, s := range strings.Split(msg.Params[3], " ") { for _, s := range strings.Split(members, " ") {
membership, nick := parseMembershipPrefix(s) membership, nick := parseMembershipPrefix(s)
ch.Members[nick] = membership ch.Members[nick] = membership
} }
case irc.RPL_ENDOFNAMES: case irc.RPL_ENDOFNAMES:
if len(msg.Params) < 2 { var name string
return newNeedMoreParamsError(msg.Command) if err := parseMessageParams(msg, nil, &name); err != nil {
return err
} }
ch, err := c.getChannel(msg.Params[1]) ch, err := c.getChannel(name)
if err != nil { if err != nil {
return err return err
} }
@ -322,7 +325,6 @@ func (c *upstreamConn) readMessages() error {
Command: "NICK", Command: "NICK",
Params: []string{c.upstream.Nick}, Params: []string{c.upstream.Nick},
} }
c.messages <- &irc.Message{ c.messages <- &irc.Message{
Command: "USER", Command: "USER",
Params: []string{c.upstream.Username, "0", "*", c.upstream.Realname}, Params: []string{c.upstream.Username, "0", "*", c.upstream.Realname},