2016-11-13 08:30:43 +00:00
|
|
|
package girc
|
|
|
|
|
2016-11-13 11:28:01 +00:00
|
|
|
import "time"
|
2016-11-13 10:46:32 +00:00
|
|
|
|
2016-11-13 08:30:43 +00:00
|
|
|
func (c *Client) registerHelpers() {
|
2016-11-13 13:17:41 +00:00
|
|
|
c.callbacks = make(map[string][]Callback)
|
|
|
|
|
2016-11-13 14:00:39 +00:00
|
|
|
if c.Config.DisableHelpers {
|
2016-11-13 13:17:41 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2016-11-13 08:30:43 +00:00
|
|
|
c.AddBgCallback(SUCCESS, handleWelcome)
|
|
|
|
c.AddCallback(PING, handlePING)
|
|
|
|
|
2016-11-13 11:28:01 +00:00
|
|
|
// joins/parts/anything that may add/remove/rename users
|
2016-11-13 08:30:43 +00:00
|
|
|
c.AddCallback(JOIN, handleJOIN)
|
|
|
|
c.AddCallback(PART, handlePART)
|
|
|
|
c.AddCallback(KICK, handleKICK)
|
2016-11-13 11:28:01 +00:00
|
|
|
c.AddCallback(QUIT, handleKICK)
|
|
|
|
c.AddCallback(NICK, handleNICK)
|
2016-11-13 08:30:43 +00:00
|
|
|
|
|
|
|
// WHO/WHOX responses
|
|
|
|
c.AddCallback(RPL_WHOREPLY, handleWHO)
|
|
|
|
c.AddCallback(RPL_WHOSPCRPL, handleWHO)
|
|
|
|
|
|
|
|
// nickname collisions
|
|
|
|
c.AddCallback(ERR_NICKNAMEINUSE, nickCollisionHandler)
|
|
|
|
c.AddCallback(ERR_NICKCOLLISION, nickCollisionHandler)
|
|
|
|
c.AddCallback(ERR_UNAVAILRESOURCE, nickCollisionHandler)
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleWelcome is a helper function which lets the client know
|
|
|
|
// that enough time has passed and now they can send commands
|
|
|
|
//
|
|
|
|
// should always run in separate thread
|
2016-11-13 10:27:53 +00:00
|
|
|
func handleWelcome(c *Client, e Event) {
|
2016-11-13 08:30:43 +00:00
|
|
|
// this should be the nick that the server gives us. 99% of the time, it's the
|
|
|
|
// one we supplied during connection, but some networks will insta-rename users.
|
|
|
|
if len(e.Params) > 0 {
|
|
|
|
c.State.nick = e.Params[0]
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
|
|
|
|
c.Events <- &Event{Command: CONNECTED}
|
|
|
|
}
|
|
|
|
|
|
|
|
// nickCollisionHandler helps prevent the client from having conflicting
|
|
|
|
// nicknames with another bot, user, etc
|
2016-11-13 10:27:53 +00:00
|
|
|
func nickCollisionHandler(c *Client, e Event) {
|
2016-11-13 08:30:43 +00:00
|
|
|
c.SetNick(c.GetNick() + "_")
|
|
|
|
}
|
|
|
|
|
|
|
|
// handlePING helps respond to ping requests from the server
|
2016-11-13 10:27:53 +00:00
|
|
|
func handlePING(c *Client, e Event) {
|
2016-11-13 08:30:43 +00:00
|
|
|
c.Send(&Event{Command: PONG, Params: e.Params, Trailing: e.Trailing})
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleJOIN ensures that the state has updated users and channels
|
2016-11-13 10:27:53 +00:00
|
|
|
func handleJOIN(c *Client, e Event) {
|
2016-11-13 11:28:01 +00:00
|
|
|
if len(e.Params) != 1 {
|
2016-11-13 08:30:43 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// create it in state
|
|
|
|
c.State.createChanIfNotExists(e.Params[0])
|
|
|
|
|
2016-11-13 11:28:01 +00:00
|
|
|
if e.Prefix.Name == c.GetNick() {
|
|
|
|
// if it's us, don't just add our user to the list. run a WHO
|
|
|
|
// which will tell us who exactly is in the channel
|
|
|
|
c.Who(e.Params[0])
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// create the user in state. only WHO the user, which is more efficient.
|
|
|
|
c.Who(e.Prefix.Name)
|
2016-11-13 08:30:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// handlePART ensures that the state is clean of old user and channel entries
|
2016-11-13 10:27:53 +00:00
|
|
|
func handlePART(c *Client, e Event) {
|
2016-11-13 08:30:43 +00:00
|
|
|
if len(e.Params) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if e.Prefix.Name == c.GetNick() {
|
|
|
|
c.State.deleteChannel(e.Params[0])
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2016-11-13 11:28:01 +00:00
|
|
|
c.State.deleteUser(e.Prefix.Name)
|
2016-11-13 08:30:43 +00:00
|
|
|
}
|
|
|
|
|
2016-11-13 10:27:53 +00:00
|
|
|
func handleWHO(c *Client, e Event) {
|
2016-11-13 08:30:43 +00:00
|
|
|
var channel, user, host, nick string
|
|
|
|
|
|
|
|
// assume WHOX related
|
|
|
|
if e.Command == RPL_WHOSPCRPL {
|
|
|
|
if len(e.Params) != 6 {
|
|
|
|
// assume there was some form of error or invalid WHOX response
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if e.Params[1] != "1" {
|
|
|
|
// we should always be sending 1, and we should receive 1. if this
|
|
|
|
// is anything but, then we didn't send the request and we can
|
|
|
|
// ignore it.
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
channel, user, host, nick = e.Params[2], e.Params[3], e.Params[4], e.Params[5]
|
|
|
|
} else {
|
|
|
|
channel, user, host, nick = e.Params[1], e.Params[2], e.Params[3], e.Params[5]
|
|
|
|
}
|
|
|
|
|
|
|
|
c.State.createUserIfNotExists(channel, nick, user, host)
|
|
|
|
}
|
|
|
|
|
2016-11-13 10:27:53 +00:00
|
|
|
func handleKICK(c *Client, e Event) {
|
2016-11-13 08:30:43 +00:00
|
|
|
if len(e.Params) < 2 {
|
|
|
|
// needs at least channel and user
|
|
|
|
return
|
|
|
|
}
|
2016-11-13 10:46:32 +00:00
|
|
|
|
|
|
|
if e.Params[1] == c.GetNick() {
|
|
|
|
c.State.deleteChannel(e.Params[0])
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// assume it's just another user
|
2016-11-13 11:28:01 +00:00
|
|
|
c.State.deleteUser(e.Params[1])
|
|
|
|
}
|
|
|
|
|
|
|
|
func handleNICK(c *Client, e Event) {
|
|
|
|
if len(e.Params) != 1 {
|
|
|
|
// something erronous was sent to us
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.State.renameUser(e.Prefix.Name, e.Params[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
func handleQUIT(c *Client, e Event) {
|
|
|
|
c.State.deleteUser(e.Prefix.Name)
|
2016-11-13 08:30:43 +00:00
|
|
|
}
|