summaryrefslogtreecommitdiff
path: root/rooms.go
diff options
context:
space:
mode:
Diffstat (limited to 'rooms.go')
-rw-r--r--rooms.go96
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
+}