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 +} |