goirc/state/tracker.go

118 lines
2.8 KiB
Go

package state
import (
"github.com/fluffle/goirc/logging"
)
// The state manager interface
type StateTracker interface {
NewNick(nick string) *Nick
GetNick(nick string) *Nick
ReNick(old, neu string)
DelNick(nick string)
NewChannel(channel string) *Channel
GetChannel(channel string) *Channel
DelChannel(channel string)
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
}
/******************************************************************************\
* tracker methods to create/look up nicks/channels
\******************************************************************************/
func NewTracker() *stateTracker {
st := &stateTracker{}
st.initialise()
return st
}
func (st *stateTracker) initialise() {
st.nicks = make(map[string]*Nick)
st.chans = make(map[string]*Channel)
}
// Creates a new Nick, initialises it, and stores it so it
// can be properly tracked for state management purposes.
func (st *stateTracker) NewNick(nick string) *Nick {
if _, ok := st.nicks[nick]; ok {
logging.Warn("StateTracker.NewNick(): %s already tracked.", nick)
return nil
}
n := &Nick{Nick: nick, st: st}
n.initialise()
st.nicks[nick] = n
return n
}
// Returns a Nick for the nick n, if we're tracking it.
func (st *stateTracker) GetNick(n string) *Nick {
if nick, ok := st.nicks[n]; ok {
return nick
}
return nil
}
// Signals to the tracker that a Nick should be tracked
// under a "neu" nick rather than the old one.
func (st *stateTracker) ReNick(old, neu string) {
if n, ok := st.nicks[old]; ok {
st.nicks[old] = nil, false
n.Nick = neu
st.nicks[neu] = n
} else {
logging.Warn("StateTracker.ReNick(): %s not tracked.", old)
}
}
// Removes a Nick from being tracked.
func (st *stateTracker) DelNick(n string) {
if _, ok := st.nicks[n]; ok {
st.nicks[n] = nil, false
} else {
logging.Warn("StateTracker.DelNick(): %s not tracked.", n)
}
}
// Creates a new Channel, initialises it, and stores it so it
// can be properly tracked for state management purposes.
func (st *stateTracker) NewChannel(c string) *Channel {
ch := &Channel{Name: c, st: st}
ch.initialise()
st.chans[c] = ch
return ch
}
// Returns a Channel for the channel c, if we're tracking it.
func (st *stateTracker) GetChannel(c string) *Channel {
if ch, ok := st.chans[c]; ok {
return ch
}
return nil
}
// Removes a Channel from being tracked.
func (st *stateTracker) DelChannel(c string) {
if _, ok := st.chans[c]; ok {
st.chans[c] = nil, false
}
}
// Returns true if both the channel c and the nick n are tracked
// and the nick is associated with the channel.
func (st *stateTracker) IsOn(c, n string) bool {
nk := st.GetNick(n)
ch := st.GetChannel(c)
if nk != nil && ch != nil {
return nk.IsOn(ch)
}
return false
}