track user modes using NAMES; closes #2
This commit is contained in:
parent
6b4a3e6359
commit
1b41086bca
26
handlers.go
26
handlers.go
@ -27,6 +27,7 @@ func (c *Client) registerHandlers() {
|
|||||||
c.Callbacks.register(true, KICK, CallbackFunc(handleKICK))
|
c.Callbacks.register(true, KICK, CallbackFunc(handleKICK))
|
||||||
c.Callbacks.register(true, QUIT, CallbackFunc(handleQUIT))
|
c.Callbacks.register(true, QUIT, CallbackFunc(handleQUIT))
|
||||||
c.Callbacks.register(true, NICK, CallbackFunc(handleNICK))
|
c.Callbacks.register(true, NICK, CallbackFunc(handleNICK))
|
||||||
|
c.Callbacks.register(true, RPL_NAMREPLY, CallbackFunc(handleNAMES))
|
||||||
|
|
||||||
// WHO/WHOX responses.
|
// WHO/WHOX responses.
|
||||||
c.Callbacks.register(true, RPL_WHOREPLY, CallbackFunc(handleWHO))
|
c.Callbacks.register(true, RPL_WHOREPLY, CallbackFunc(handleWHO))
|
||||||
@ -310,3 +311,28 @@ func handleMOTD(c *Client, e Event) {
|
|||||||
|
|
||||||
c.state.mu.Unlock()
|
c.state.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleNAMES(c *Client, e Event) {
|
||||||
|
if len(e.Params) < 1 || !IsValidChannel(e.Params[len(e.Params)-1]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(e.Trailing, " ")
|
||||||
|
|
||||||
|
c.state.mu.Lock()
|
||||||
|
for i := 0; i < len(parts); i++ {
|
||||||
|
modes, nick, ok := parseUserModes(parts[i])
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
user := c.state.createUserIfNotExists(e.Params[len(e.Params)-1], nick)
|
||||||
|
if user == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't append modes, overwrite them.
|
||||||
|
user.Modes.setModes(modes, false)
|
||||||
|
}
|
||||||
|
c.state.mu.Unlock()
|
||||||
|
}
|
||||||
|
103
state.go
103
state.go
@ -74,6 +74,12 @@ type User struct {
|
|||||||
// Only usable if from state, not in past.
|
// Only usable if from state, not in past.
|
||||||
LastActive time.Time
|
LastActive time.Time
|
||||||
|
|
||||||
|
// Modes are the user modes applied to this user that affect the given
|
||||||
|
// channel. This supports non-rfc style modes like Admin, Owner, and HalfOp.
|
||||||
|
// If you want to easily check if a user has permissions equal or greater
|
||||||
|
// than OP, use Modes.IsAdmin().
|
||||||
|
Modes UserModes
|
||||||
|
|
||||||
// Extras are things added on by additional tracking methods, which may
|
// Extras are things added on by additional tracking methods, which may
|
||||||
// or may not work on the IRC server in mention.
|
// or may not work on the IRC server in mention.
|
||||||
Extras struct {
|
Extras struct {
|
||||||
@ -317,3 +323,100 @@ func (s *state) getUsers(matchType, toMatch string) []*User {
|
|||||||
|
|
||||||
return users
|
return users
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UserModes contains all channel-based user permissions. The minimum op, and
|
||||||
|
// voice should be supported on all networks. This also supports non-rfc
|
||||||
|
// Owner, Admin, and HalfOp, if the network has support for it.
|
||||||
|
type UserModes struct {
|
||||||
|
// Owner (non-rfc) indicates that the user has full permissions to the
|
||||||
|
// channel. More than one user can have owner permission.
|
||||||
|
Owner bool
|
||||||
|
// Admin (non-rfc) is commonly given to users that are trusted enough
|
||||||
|
// to manage channel permissions, as well as higher level service settings.
|
||||||
|
Admin bool
|
||||||
|
// Op is commonly given to trusted users who can manage a given channel
|
||||||
|
// by kicking, and banning users.
|
||||||
|
Op bool
|
||||||
|
// HalfOp (non-rfc) is commonly used to give users permissions like the
|
||||||
|
// ability to kick, without giving them greater abilities to ban all users.
|
||||||
|
HalfOp bool
|
||||||
|
// Voice indicates the user has voice permissions, commonly given to known
|
||||||
|
// users, wih very light trust, or to indicate a user is active.
|
||||||
|
Voice bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAdmin indicates that the user has banning abilities, and are likely a
|
||||||
|
// very trustable user (e.g. op+).
|
||||||
|
func (m UserModes) IsAdmin() bool {
|
||||||
|
if m.Owner || m.Admin || m.Op {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAdmin indicates that the user at least has modes set upon them, higher
|
||||||
|
// than a regular joining user.
|
||||||
|
func (m UserModes) IsTrusted() bool {
|
||||||
|
if m.IsAdmin() || m.HalfOp || m.Voice {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset resets the modes of a user.
|
||||||
|
func (m *UserModes) reset() {
|
||||||
|
m.Owner = false
|
||||||
|
m.Admin = false
|
||||||
|
m.Op = false
|
||||||
|
m.HalfOp = false
|
||||||
|
m.Voice = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// setMode translates raw mode characters into proper permissions. Only use
|
||||||
|
// this function when you have a session lock.
|
||||||
|
func (m *UserModes) setModes(modes string, append bool) {
|
||||||
|
if !append {
|
||||||
|
m.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(modes); i++ {
|
||||||
|
switch string(modes[i]) {
|
||||||
|
case OwnerPrefix:
|
||||||
|
m.Owner = true
|
||||||
|
case AdminPrefix:
|
||||||
|
m.Admin = true
|
||||||
|
case OperatorPrefix:
|
||||||
|
m.Op = true
|
||||||
|
case HalfOperatorPrefix:
|
||||||
|
m.HalfOp = true
|
||||||
|
case VoicePrefix:
|
||||||
|
m.Voice = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseUserModes parses a raw mode line, like "@user" or "@+user".
|
||||||
|
func parseUserModes(raw string) (modes, nick string, success bool) {
|
||||||
|
for i := 0; i < len(raw); i++ {
|
||||||
|
char := string(raw[i])
|
||||||
|
|
||||||
|
if char == OwnerPrefix || char == AdminPrefix || char == HalfOperatorPrefix ||
|
||||||
|
char == OperatorPrefix || char == VoicePrefix {
|
||||||
|
modes += char
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume we've gotten to the nickname part.
|
||||||
|
if !IsValidNick(raw[i:]) {
|
||||||
|
return modes, nick, false
|
||||||
|
}
|
||||||
|
|
||||||
|
nick = raw[i:]
|
||||||
|
|
||||||
|
return modes, nick, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user