diff options
Diffstat (limited to 'rooms.go')
| -rw-r--r-- | rooms.go | 96 | 
1 files changed, 96 insertions, 0 deletions
| diff --git a/rooms.go b/rooms.go new file mode 100644 index 0000000..4aa8542 --- /dev/null +++ b/rooms.go @@ -0,0 +1,96 @@ +package main + +import ( +	"encoding/json" +	"errors" +) + +type MsgType int + +const ( +	MsgChat MsgType = iota // Default +	MsgJoin +	MsgLeave +) + +func (mt *MsgType) MarshalJSON() ([]byte, error) { +	switch *mt { +	case MsgChat: +		return json.Marshal("chat") +	case MsgJoin: +		return json.Marshal("join") +	case MsgLeave: +		return json.Marshal("leave") +	} + +	return nil, errors.New("Unknown message type") +} + +type Message struct { +	Type MsgType `json:"type"` +	User string  `json:"user"` +	Text string  `json:"text,omitempty"` +} + +type Room struct { +	Messages chan Message +	Buddies  map[string]Buddy +} + +func NewRoom() (r *Room) { +	r = new(Room) +	r.Messages = make(chan Message) +	r.Buddies = make(map[string]Buddy) +	go r.Broadcast() +} + +func (r *Room) Leave(nick string) { +	if _, ok := r.Buddies[nick]; !ok { +		return +	} + +	delete(r.Buddies[nick]) +	if len(r.Buddies) == 0 { +		close(r.Messages) +	} else { +		r.Messages <- Message{ +			Type: MsgLeave, +			From: nick, +		} +	} +} + +func (r *Room) Broadcast() { +	for m := range r.Messages { +		for _, buddy := range r.Buddies { +			buddy.Receive <- m // TODO: What happens when this locks? +		} +	} +} + +var rooms = make(map[string]Room) + +func Join(room, nick string) (*Buddy, error) { +	r, ok := rooms[room] +	if !ok { +		r = NewRoom() +		rooms[room] = r +	} + +	if _, there := r.Buddies[nick]; there { +		return nil, errors.New("Nickname is already in use") +	} + +	if len(r.Buddies) >= *perroom { +		return nil, errors.New("Room is full") +	} + +	r.Messages <- Message{ +		Type: MsgJoin, +		From: nick, +	} + +	b := NewBuddy(nick, r) +	r.Buddies[nick] = b +	return b, nil +} | 
