Tracking wip.

This commit is contained in:
Alex Bramley 2011-09-28 20:48:58 +01:00
parent c400a2141a
commit eb6ac4ce05
2 changed files with 64 additions and 29 deletions

View File

@ -27,10 +27,8 @@ type Conn struct {
Registry event.EventRegistry
Dispatcher event.EventDispatcher
// Map of channels we're on
chans map[string]*Channel
// Map of nicks we know about
nicks map[string]*Nick
// State tracker for nicks and channels
Tracker StateTracker
// Use the State field to store external state that handlers might need.
// Remember ... you might need locking for this ;-)

View File

@ -5,16 +5,41 @@ package client
import (
"fmt"
"os"
"reflect"
"strconv"
)
// The state manager interface
type StateTracker interface {
NewNick(nick string) *Nick
GetNick(nick string) *Nick
NewChannel(channel string) *Channel
GetChannel(channel string) *Channel
IsOn(channel, nick string) bool
}
// ... and a struct to implement it
type stateTracker struct {
// Map of channels we're on
chans map[string]*Channel
// Map of nicks we know about
nicks map[string]*Nick
// A pointer to the connection whose state this tracks
conn *Conn
// Logging interface
l Logger
}
// A struct representing an IRC channel
type Channel struct {
Name, Topic string
Modes *ChanMode
Nicks map[*Nick]*ChanPrivs
conn *Conn
st StateTracker
}
// A struct representing an IRC nick
@ -22,7 +47,7 @@ type Nick struct {
Nick, Ident, Host, Name string
Modes *NickMode
Channels map[*Channel]*ChanPrivs
conn *Conn
st StateTracker
}
// A struct representing the modes of an IRC Channel
@ -60,45 +85,46 @@ type ChanPrivs struct {
}
/******************************************************************************\
* Conn methods to create/look up nicks/channels
* tracker methods to create/look up nicks/channels
\******************************************************************************/
// Creates a new *irc.Nick, initialises it, and stores it in *irc.Conn so it
// Creates a new *irc.Nick, initialises it, and stores it so it
// can be properly tracked for state management purposes.
func (conn *Conn) NewNick(nick, ident, name, host string) *Nick {
n := &Nick{Nick: nick, Ident: ident, Name: name, Host: host, conn: conn}
func (st *stateTracker) NewNick(nick string) *Nick {
n := &Nick{Nick: nick, st: st}
n.initialise()
conn.nicks[n.Nick] = n
st.nicks[nick] = n
return n
}
// Returns an *irc.Nick for the nick n, if we're tracking it.
func (conn *Conn) GetNick(n string) *Nick {
if nick, ok := conn.nicks[n]; ok {
func (st *stateTracker) GetNick(n string) *Nick {
if nick, ok := st.nicks[n]; ok {
return nick
}
return nil
}
// Creates a new *irc.Channel, initialises it, and stores it in *irc.Conn so it
// Creates a new *irc.Channel, initialises it, and stores it so it
// can be properly tracked for state management purposes.
func (conn *Conn) NewChannel(c string) *Channel {
ch := &Channel{Name: c, conn: conn}
func (st *stateTracker) NewChannel(c string) *Channel {
ch := &Channel{Name: c, st: st}
ch.initialise()
conn.chans[ch.Name] = ch
st.chans[c] = ch
return ch
}
// Returns an *irc.Channel for the channel c, if we're tracking it.
func (conn *Conn) GetChannel(c string) *Channel {
if ch, ok := conn.chans[c]; ok {
func (st *stateTracker) GetChannel(c string) *Channel {
if ch, ok := st.chans[c]; ok {
return ch
}
return nil
}
// Parses mode strings for a channel
func (conn *Conn) ParseChannelModes(ch *Channel, modes string, modeargs []string) {
func (ch *Channel) ParseModes(modes string, modeargs []string) os.Error {
var modeop bool // true => add mode, false => remove mode
var modestr string
for i := 0; i < len(modes); i++ {
@ -126,21 +152,29 @@ func (conn *Conn) ParseChannelModes(ch *Channel, modes string, modeargs []string
case 'O':
ch.Modes.OperOnly = modeop
case 'k':
if len(modeargs) != 0 {
if modeop && len(modeargs) != 0 {
ch.Modes.Key, modeargs = modeargs[0], modeargs[1:]
} else if !modeop {
ch.Modes.Key = ""
} else {
conn.error("irc.ParseChanModes(): buh? not enough arguments to process MODE %s %s%s", ch.Name, modestr, m)
return os.NewError(fmt.Sprintf(
"irc.ParseChanModes(): buh? not enough arguments to process MODE %s %s%s",
ch.Name, modestr, m))
}
case 'l':
if len(modeargs) != 0 {
if modeop && len(modeargs) != 0 {
ch.Modes.Limit, _ = strconv.Atoi(modeargs[0])
modeargs = modeargs[1:]
} else {
conn.error("irc.ParseChanModes(): buh? not enough arguments to process MODE %s %s%s", ch.Name, modestr, m)
} else if !modeop {
ch.Modes.Limit = 0
}
return os.NewError(fmt.Sprintf(
"Channel.ParseModes(): buh? not enough arguments to process MODE %s %s%s",
ch.Name, modestr, m))
}
case 'q', 'a', 'o', 'h', 'v':
if len(modeargs) != 0 {
n := conn.GetNick(modeargs[0])
n := ch.st.GetNick(modeargs[0])
if p, ok := ch.Nicks[n]; ok && n != nil {
switch m {
case 'q':
@ -156,17 +190,20 @@ func (conn *Conn) ParseChannelModes(ch *Channel, modes string, modeargs []string
}
modeargs = modeargs[1:]
} else {
conn.error("irc.ParseChanModes(): MODE %s %s%s %s: buh? state tracking failure.", ch.Name, modestr, m, modeargs[0])
return os.NewError(fmt.Sprintf(
"Channel.ParseModes(): MODE %s %s%s %s: buh? state tracking failure.",
ch.Name, modestr, m, modeargs[0]))
}
} else {
conn.error("irc.ParseChanModes(): buh? not enough arguments to process MODE %s %s%s", ch.Name, modestr, m)
conn.error("Channel.ParseModes(): buh? not enough arguments to process MODE %s %s%s", ch.Name, modestr, m)
}
}
}
return nil
}
// Parse mode strings for a nick
func (conn *Conn) ParseNickModes(n *Nick, modes string) {
func (n *Nick) ParseModes(modes string) {
var modeop bool // true => add mode, false => remove mode
for i := 0; i < len(modes); i++ {
switch m := modes[i]; m {