mirror of
https://github.com/ergochat/ergo.git
synced 2025-12-20 02:00:11 -08:00
parent
4cadb7ad58
commit
cb530050f1
3 changed files with 46 additions and 46 deletions
|
|
@ -12,25 +12,24 @@ import (
|
|||
// MonitorManager keeps track of who's monitoring which nicks.
|
||||
type MonitorManager struct {
|
||||
sync.RWMutex // tier 2
|
||||
// client -> nicks it's watching
|
||||
watching map[*Client]map[string]bool
|
||||
// nick -> clients watching it
|
||||
watchedby map[string]map[*Client]bool
|
||||
// (all nicks must be normalized externally by casefolding)
|
||||
// client -> (casefolded nick it's watching -> uncasefolded nick)
|
||||
watching map[*Session]map[string]string
|
||||
// casefolded nick -> clients watching it
|
||||
watchedby map[string]map[*Session]empty
|
||||
}
|
||||
|
||||
func (mm *MonitorManager) Initialize() {
|
||||
mm.watching = make(map[*Client]map[string]bool)
|
||||
mm.watchedby = make(map[string]map[*Client]bool)
|
||||
mm.watching = make(map[*Session]map[string]string)
|
||||
mm.watchedby = make(map[string]map[*Session]empty)
|
||||
}
|
||||
|
||||
// AlertAbout alerts everyone monitoring `client`'s nick that `client` is now {on,off}line.
|
||||
func (manager *MonitorManager) AlertAbout(nick, cfnick string, online bool) {
|
||||
var watchers []*Client
|
||||
var watchers []*Session
|
||||
// safely copy the list of clients watching our nick
|
||||
manager.RLock()
|
||||
for client := range manager.watchedby[cfnick] {
|
||||
watchers = append(watchers, client)
|
||||
for session := range manager.watchedby[cfnick] {
|
||||
watchers = append(watchers, session)
|
||||
}
|
||||
manager.RUnlock()
|
||||
|
||||
|
|
@ -39,58 +38,67 @@ func (manager *MonitorManager) AlertAbout(nick, cfnick string, online bool) {
|
|||
command = RPL_MONONLINE
|
||||
}
|
||||
|
||||
for _, mClient := range watchers {
|
||||
mClient.Send(nil, mClient.server.name, command, mClient.Nick(), nick)
|
||||
for _, session := range watchers {
|
||||
session.Send(nil, session.client.server.name, command, session.client.Nick(), nick)
|
||||
}
|
||||
}
|
||||
|
||||
// Add registers `client` to receive notifications about `nick`.
|
||||
func (manager *MonitorManager) Add(client *Client, nick string, limit int) error {
|
||||
func (manager *MonitorManager) Add(session *Session, nick string, limit int) error {
|
||||
cfnick, err := CasefoldName(nick)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
manager.Lock()
|
||||
defer manager.Unlock()
|
||||
|
||||
if manager.watching[client] == nil {
|
||||
manager.watching[client] = make(map[string]bool)
|
||||
if manager.watching[session] == nil {
|
||||
manager.watching[session] = make(map[string]string)
|
||||
}
|
||||
if manager.watchedby[nick] == nil {
|
||||
manager.watchedby[nick] = make(map[*Client]bool)
|
||||
if manager.watchedby[cfnick] == nil {
|
||||
manager.watchedby[cfnick] = make(map[*Session]empty)
|
||||
}
|
||||
|
||||
if len(manager.watching[client]) >= limit {
|
||||
if len(manager.watching[session]) >= limit {
|
||||
return errMonitorLimitExceeded
|
||||
}
|
||||
|
||||
manager.watching[client][nick] = true
|
||||
manager.watchedby[nick][client] = true
|
||||
manager.watching[session][cfnick] = nick
|
||||
manager.watchedby[cfnick][session] = empty{}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove unregisters `client` from receiving notifications about `nick`.
|
||||
func (manager *MonitorManager) Remove(client *Client, nick string) error {
|
||||
func (manager *MonitorManager) Remove(session *Session, nick string) (err error) {
|
||||
cfnick, err := CasefoldName(nick)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
manager.Lock()
|
||||
defer manager.Unlock()
|
||||
// deleting from nil maps is fine
|
||||
delete(manager.watching[client], nick)
|
||||
delete(manager.watchedby[nick], client)
|
||||
delete(manager.watching[session], cfnick)
|
||||
delete(manager.watchedby[cfnick], session)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveAll unregisters `client` from receiving notifications about *all* nicks.
|
||||
func (manager *MonitorManager) RemoveAll(client *Client) {
|
||||
func (manager *MonitorManager) RemoveAll(session *Session) {
|
||||
manager.Lock()
|
||||
defer manager.Unlock()
|
||||
|
||||
for nick := range manager.watching[client] {
|
||||
delete(manager.watchedby[nick], client)
|
||||
for cfnick := range manager.watching[session] {
|
||||
delete(manager.watchedby[cfnick], session)
|
||||
}
|
||||
delete(manager.watching, client)
|
||||
delete(manager.watching, session)
|
||||
}
|
||||
|
||||
// List lists all nicks that `client` is registered to receive notifications about.
|
||||
func (manager *MonitorManager) List(client *Client) (nicks []string) {
|
||||
func (manager *MonitorManager) List(session *Session) (nicks []string) {
|
||||
manager.RLock()
|
||||
defer manager.RUnlock()
|
||||
for nick := range manager.watching[client] {
|
||||
for _, nick := range manager.watching[session] {
|
||||
nicks = append(nicks, nick)
|
||||
}
|
||||
return nicks
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue