Skip to content

Commit

Permalink
move away from Event.Trailing
Browse files Browse the repository at this point in the history
* initial work towards moving away from Event.Trailing

* Event.Trailing() -> Event.Last()

* fix incorrect go.mod/go.sum files

* fixes for pretty printed topics and CTCPs

* remove unneeded whitespace check

* clarify potential contents of Event.Params

* better splitting of hopcount from realname
  • Loading branch information
lrstanley authored Feb 10, 2019
1 parent c1e59a0 commit 51b8e09
Show file tree
Hide file tree
Showing 14 changed files with 200 additions and 213 deletions.
81 changes: 40 additions & 41 deletions builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func handleConnect(c *Client, e Event) {
}

time.Sleep(2 * time.Second)
c.RunHandlers(&Event{Command: CONNECTED, Trailing: c.Server()})
c.RunHandlers(&Event{Command: CONNECTED, Params: []string{c.Server()}})
}

// nickCollisionHandler helps prevent the client from having conflicting
Expand All @@ -109,7 +109,7 @@ func nickCollisionHandler(c *Client, e Event) {

// handlePING helps respond to ping requests from the server.
func handlePING(c *Client, e Event) {
c.Cmd.Pong(e.Trailing)
c.Cmd.Pong(e.Last())
}

func handlePONG(c *Client, e Event) {
Expand All @@ -120,16 +120,11 @@ func handlePONG(c *Client, e Event) {

// handleJOIN ensures that the state has updated users and channels.
func handleJOIN(c *Client, e Event) {
if e.Source == nil {
if e.Source == nil || len(e.Params) == 0 {
return
}

var channelName string
if len(e.Params) > 0 {
channelName = e.Params[0]
} else {
channelName = e.Trailing
}
channelName := e.Params[0]

c.state.Lock()

Expand Down Expand Up @@ -158,13 +153,13 @@ func handleJOIN(c *Client, e Event) {
user.addChannel(channel.Name)

// Assume extended-join (ircv3).
if len(e.Params) == 2 {
if len(e.Params) >= 2 {
if e.Params[1] != "*" {
user.Extras.Account = e.Params[1]
}

if len(e.Trailing) > 0 {
user.Extras.Name = e.Trailing
if len(e.Params) > 2 {
user.Extras.Name = e.Params[2]
}
}
c.state.Unlock()
Expand Down Expand Up @@ -192,16 +187,13 @@ func handleJOIN(c *Client, e Event) {

// handlePART ensures that the state is clean of old user and channel entries.
func handlePART(c *Client, e Event) {
if e.Source == nil {
if e.Source == nil || len(e.Params) < 1 {
return
}

var channel string
if len(e.Params) > 0 {
channel = e.Params[0]
} else {
channel = e.Trailing
}
// TODO: does this work if it's not the bot?

channel := e.Params[0]

if channel == "" {
return
Expand Down Expand Up @@ -231,7 +223,7 @@ func handleTOPIC(c *Client, e Event) {
case 1:
name = e.Params[0]
default:
name = e.Params[len(e.Params)-1]
name = e.Params[1]
}

c.state.Lock()
Expand All @@ -241,7 +233,7 @@ func handleTOPIC(c *Client, e Event) {
return
}

channel.Topic = e.Trailing
channel.Topic = e.Last()
c.state.Unlock()
c.state.notify(c, UPDATE_STATE)
}
Expand All @@ -253,7 +245,7 @@ func handleWHO(c *Client, e Event) {

// Assume WHOX related.
if e.Command == RPL_WHOSPCRPL {
if len(e.Params) != 7 {
if len(e.Params) != 8 {
// Assume there was some form of error or invalid WHOX response.
return
}
Expand All @@ -266,12 +258,24 @@ func handleWHO(c *Client, e Event) {
}

ident, host, nick, account = e.Params[3], e.Params[4], e.Params[5], e.Params[6]
realname = e.Trailing
realname = e.Last()
} else {
// Assume RPL_WHOREPLY.
ident, host, nick = e.Params[2], e.Params[3], e.Params[5]
if len(e.Trailing) > 2 {
realname = e.Trailing[2:]
// format: "<client> <channel> <user> <host> <server> <nick> <H|G>[*][@|+] :<hopcount> <real_name>"
ident, host, nick, realname = e.Params[2], e.Params[3], e.Params[5], e.Last()

// Strip the numbers from "<hopcount> <realname>"
for i := 0; i < len(realname); i++ {
// Check if it's not 0-9.
if realname[i] < 0x30 || i > 0x39 {
realname = strings.TrimLeft(realname[i+1:], " ")
break
}

if i == len(realname)-1 {
// Assume it's only numbers?
realname = ""
}
}
}

Expand Down Expand Up @@ -326,10 +330,8 @@ func handleNICK(c *Client, e Event) {

c.state.Lock()
// renameUser updates the LastActive time automatically.
if len(e.Params) == 1 {
c.state.renameUser(e.Source.ID(), e.Params[0])
} else if len(e.Trailing) > 0 {
c.state.renameUser(e.Source.ID(), e.Trailing)
if len(e.Params) >= 1 {
c.state.renameUser(e.Source.ID(), e.Last())
}
c.state.Unlock()
c.state.notify(c, UPDATE_STATE)
Expand Down Expand Up @@ -372,12 +374,10 @@ func handleMYINFO(c *Client, e Event) {
// events. These commonly contain the server capabilities and limitations.
// For example, things like max channel name length, or nickname length.
func handleISUPPORT(c *Client, e Event) {
// Must be a ISUPPORT-based message. 005 is also used for server bounce
// related things, so this handler may be triggered during other
// situations.
// Must be a ISUPPORT-based message.

// Also known as RPL_PROTOCTL.
if !strings.HasSuffix(e.Trailing, "this server") {
if !strings.HasSuffix(e.Last(), "this server") {
return
}

Expand All @@ -387,8 +387,8 @@ func handleISUPPORT(c *Client, e Event) {
}

c.state.Lock()
// Skip the first parameter, as it's our nickname.
for i := 1; i < len(e.Params); i++ {
// Skip the first parameter, as it's our nickname, and the last, as it's the doc.
for i := 1; i < len(e.Params)-1; i++ {
j := strings.IndexByte(e.Params[i], '=')

if j < 1 || (j+1) == len(e.Params[i]) {
Expand Down Expand Up @@ -421,10 +421,9 @@ func handleMOTD(c *Client, e Event) {

// Otherwise, assume we're getting sent the MOTD line-by-line.
if len(c.state.motd) != 0 {
e.Trailing = "\n" + e.Trailing
c.state.motd += "\n"
}

c.state.motd += e.Trailing
c.state.motd += e.Last()
c.state.Unlock()
}

Expand All @@ -436,12 +435,12 @@ func handleNAMES(c *Client, e Event) {
return
}

channel := c.state.lookupChannel(e.Params[len(e.Params)-1])
channel := c.state.lookupChannel(e.Params[2])
if channel == nil {
return
}

parts := strings.Split(e.Trailing, " ")
parts := strings.Split(e.Last(), " ")

var modes, nick string
var ok bool
Expand Down
18 changes: 9 additions & 9 deletions cap.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,18 @@ func handleCAP(c *Client, e Event) {
}

// We can assume there was a failure attempting to enable a capability.
if len(e.Params) == 2 && e.Params[1] == CAP_NAK {
if len(e.Params) >= 2 && e.Params[1] == CAP_NAK {
// Let the server know that we're done.
c.write(&Event{Command: CAP, Params: []string{CAP_END}})
return
}

possible := possibleCapList(c)

if len(e.Params) >= 2 && e.Params[1] == CAP_LS {
if len(e.Params) >= 3 && e.Params[1] == CAP_LS {
c.state.Lock()

caps := parseCap(e.Trailing)
caps := parseCap(e.Last())

for k := range caps {
if _, ok := possible[k]; !ok {
Expand Down Expand Up @@ -137,17 +137,17 @@ func handleCAP(c *Client, e Event) {
}
c.state.Unlock()

// Indicates if this is a multi-line LS. (2 args means it's the
// Indicates if this is a multi-line LS. (3 args means it's the
// last LS).
if len(e.Params) == 2 {
if len(e.Params) == 3 {
// If we support no caps, just ack the CAP message and END.
if len(c.state.tmpCap) == 0 {
c.write(&Event{Command: CAP, Params: []string{CAP_END}})
return
}

// Let them know which ones we'd like to enable.
c.write(&Event{Command: CAP, Params: []string{CAP_REQ}, Trailing: strings.Join(c.state.tmpCap, " "), EmptyTrailing: true})
c.write(&Event{Command: CAP, Params: []string{CAP_REQ, strings.Join(c.state.tmpCap, " ")}})

// Re-initialize the tmpCap, so if we get multiple 'CAP LS' requests
// due to cap-notify, we can re-evaluate what we can support.
Expand All @@ -157,9 +157,9 @@ func handleCAP(c *Client, e Event) {
}
}

if len(e.Params) == 2 && len(e.Trailing) > 1 && e.Params[1] == CAP_ACK {
if len(e.Params) == 3 && e.Params[1] == CAP_ACK {
c.state.Lock()
c.state.enabledCap = strings.Split(e.Trailing, " ")
c.state.enabledCap = strings.Split(e.Last(), " ")

// Do we need to do sasl auth?
wantsSASL := false
Expand Down Expand Up @@ -208,7 +208,7 @@ func handleAWAY(c *Client, e Event) {
c.state.Lock()
user := c.state.lookupUser(e.Source.Name)
if user != nil {
user.Extras.Away = e.Trailing
user.Extras.Away = e.Last()
}
c.state.Unlock()
c.state.notify(c, UPDATE_STATE)
Expand Down
9 changes: 4 additions & 5 deletions cap_sasl.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,9 @@ func handleSASL(c *Client, e Event) {
// some reason. The SASL spec and IRCv3 spec do not define a clear
// way to abort a SASL exchange, other than to disconnect, or proceed
// with CAP END.
c.rx <- &Event{Command: ERROR, Trailing: fmt.Sprintf(
"closing connection: SASL %s failed: %s",
c.Config.SASL.Method(), e.Trailing,
)}
c.rx <- &Event{Command: ERROR, Params: []string{
fmt.Sprintf("closing connection: SASL %s failed: %s", c.Config.SASL.Method(), e.Last()),
}}
return
}

Expand Down Expand Up @@ -133,5 +132,5 @@ func handleSASLError(c *Client, e Event) {
// Authentication failed. The SASL spec and IRCv3 spec do not define a
// clear way to abort a SASL exchange, other than to disconnect, or
// proceed with CAP END.
c.rx <- &Event{Command: ERROR, Trailing: "closing connection: " + e.Trailing}
c.rx <- &Event{Command: ERROR, Params: []string{"closing connection: " + e.Last()}}
}
2 changes: 1 addition & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ func (e *ErrEvent) Error() string {
return "unknown error occurred"
}

return e.Event.Trailing
return e.Event.Last()
}

func (c *Client) execLoop(ctx context.Context, errs chan error, wg *sync.WaitGroup) {
Expand Down
2 changes: 1 addition & 1 deletion cmdhandler/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func (ch *CmdHandler) Execute(client *girc.Client, event girc.Event) {
return
}

parsed := ch.re.FindStringSubmatch(event.Trailing)
parsed := ch.re.FindStringSubmatch(event.Last())
if len(parsed) != 3 {
return
}
Expand Down
15 changes: 7 additions & 8 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (cmd *Commands) Part(channels ...string) {

// PartMessage leaves an IRC channel with a specified leave message.
func (cmd *Commands) PartMessage(channel, message string) {
cmd.c.Send(&Event{Command: PART, Params: []string{channel}, Trailing: message, EmptyTrailing: true})
cmd.c.Send(&Event{Command: PART, Params: []string{channel, message}})
}

// SendCTCP sends a CTCP request to target. Note that this method uses
Expand Down Expand Up @@ -105,7 +105,7 @@ func (cmd *Commands) SendCTCPReply(target, ctcpType, message string) {

// Message sends a PRIVMSG to target (either channel, service, or user).
func (cmd *Commands) Message(target, message string) {
cmd.c.Send(&Event{Command: PRIVMSG, Params: []string{target}, Trailing: message, EmptyTrailing: true})
cmd.c.Send(&Event{Command: PRIVMSG, Params: []string{target, message}})
}

// Messagef sends a formated PRIVMSG to target (either channel, service, or
Expand Down Expand Up @@ -171,9 +171,8 @@ func (cmd *Commands) ReplyTof(event Event, format string, a ...interface{}) {
// or user).
func (cmd *Commands) Action(target, message string) {
cmd.c.Send(&Event{
Command: PRIVMSG,
Params: []string{target},
Trailing: fmt.Sprintf("\001ACTION %s\001", message),
Command: PRIVMSG,
Params: []string{target, fmt.Sprintf("\001ACTION %s\001", message)},
})
}

Expand All @@ -185,7 +184,7 @@ func (cmd *Commands) Actionf(target, format string, a ...interface{}) {

// Notice sends a NOTICE to target (either channel, service, or user).
func (cmd *Commands) Notice(target, message string) {
cmd.c.Send(&Event{Command: NOTICE, Params: []string{target}, Trailing: message, EmptyTrailing: true})
cmd.c.Send(&Event{Command: NOTICE, Params: []string{target, message}})
}

// Noticef sends a formated NOTICE to target (either channel, service, or
Expand Down Expand Up @@ -221,7 +220,7 @@ func (cmd *Commands) SendRawf(format string, a ...interface{}) error {
// Topic sets the topic of channel to message. Does not verify the length
// of the topic.
func (cmd *Commands) Topic(channel, message string) {
cmd.c.Send(&Event{Command: TOPIC, Params: []string{channel}, Trailing: message, EmptyTrailing: true})
cmd.c.Send(&Event{Command: TOPIC, Params: []string{channel, message}})
}

// Who sends a WHO query to the server, which will attempt WHOX by default.
Expand Down Expand Up @@ -266,7 +265,7 @@ func (cmd *Commands) Oper(user, pass string) {
// server.
func (cmd *Commands) Kick(channel, user, reason string) {
if reason != "" {
cmd.c.Send(&Event{Command: KICK, Params: []string{channel, user}, Trailing: reason, EmptyTrailing: true})
cmd.c.Send(&Event{Command: KICK, Params: []string{channel, user, reason}})
}

cmd.c.Send(&Event{Command: KICK, Params: []string{channel, user}})
Expand Down
12 changes: 6 additions & 6 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,17 +309,17 @@ func (c *Client) internalConnect(mock net.Conn, dialer Dialer) error {
c.Config.Name = c.Config.User
}

c.write(&Event{Command: USER, Params: []string{c.Config.User, "*", "*"}, Trailing: c.Config.Name})
c.write(&Event{Command: USER, Params: []string{c.Config.User, "*", "*", c.Config.Name}})

// Send a virtual event allowing hooks for successful socket connection.
c.RunHandlers(&Event{Command: INITIALIZED, Trailing: c.Server()})
c.RunHandlers(&Event{Command: INITIALIZED, Params: []string{c.Server()}})

// Wait for the first error.
var result error
select {
case <-ctx.Done():
c.debug.Print("received request to close, beginning clean up")
c.RunHandlers(&Event{Command: CLOSED, Trailing: c.Server()})
c.RunHandlers(&Event{Command: CLOSED, Params: []string{c.Server()}})
case err := <-errs:
c.debug.Print("received error, beginning clean up")
result = err
Expand All @@ -336,7 +336,7 @@ func (c *Client) internalConnect(mock net.Conn, dialer Dialer) error {
c.conn.mu.Unlock()
c.mu.RUnlock()

c.RunHandlers(&Event{Command: DISCONNECTED, Trailing: c.Server()})
c.RunHandlers(&Event{Command: DISCONNECTED, Params: []string{c.Server()}})

// Once we have our error/result, let all other functions know we're done.
c.debug.Print("waiting for all routines to finish")
Expand Down Expand Up @@ -396,9 +396,9 @@ func (c *Client) Send(event *Event) {
<-time.After(c.conn.rate(event.Len()))
}

if c.Config.GlobalFormat && event.Trailing != "" &&
if c.Config.GlobalFormat && len(event.Params) > 0 && event.Params[len(event.Params)-1] != "" &&
(event.Command == PRIVMSG || event.Command == TOPIC || event.Command == NOTICE) {
event.Trailing = Fmt(event.Trailing)
event.Params[len(event.Params)-1] = Fmt(event.Params[len(event.Params)-1])
}

c.write(event)
Expand Down
Loading

0 comments on commit 51b8e09

Please sign in to comment.