2014-12-21 01:45:10 +01:00
|
|
|
package chat
|
|
|
|
|
2014-12-21 05:21:41 +01:00
|
|
|
import "fmt"
|
|
|
|
|
2014-12-21 01:45:10 +01:00
|
|
|
const historyLen = 20
|
2014-12-23 06:47:07 +01:00
|
|
|
const channelBuffer = 10
|
2014-12-21 01:45:10 +01:00
|
|
|
|
|
|
|
// Channel definition, also a Set of User Items
|
|
|
|
type Channel struct {
|
2014-12-21 05:21:41 +01:00
|
|
|
topic string
|
|
|
|
history *History
|
|
|
|
users *Set
|
2014-12-23 06:47:07 +01:00
|
|
|
broadcast chan Message
|
2014-12-21 01:45:10 +01:00
|
|
|
}
|
|
|
|
|
2014-12-23 06:47:07 +01:00
|
|
|
// Create new channel and start broadcasting goroutine.
|
2014-12-23 07:21:07 +01:00
|
|
|
func NewChannel() *Channel {
|
2014-12-23 06:47:07 +01:00
|
|
|
broadcast := make(chan Message, channelBuffer)
|
|
|
|
|
2014-12-21 01:45:10 +01:00
|
|
|
ch := Channel{
|
2014-12-21 05:21:41 +01:00
|
|
|
broadcast: broadcast,
|
|
|
|
history: NewHistory(historyLen),
|
|
|
|
users: NewSet(),
|
2014-12-21 01:45:10 +01:00
|
|
|
}
|
2014-12-23 06:47:07 +01:00
|
|
|
|
|
|
|
go func() {
|
|
|
|
for m := range broadcast {
|
2014-12-23 07:21:07 +01:00
|
|
|
// TODO: Handle commands etc?
|
2014-12-23 06:47:07 +01:00
|
|
|
ch.users.Each(func(u Item) {
|
2014-12-23 07:21:07 +01:00
|
|
|
user := u.(*User)
|
|
|
|
if m.from == user {
|
|
|
|
// Skip
|
|
|
|
return
|
|
|
|
}
|
2014-12-23 07:54:29 +01:00
|
|
|
err := user.Send(m)
|
|
|
|
if err != nil {
|
|
|
|
ch.Leave(user)
|
|
|
|
user.Close()
|
|
|
|
}
|
2014-12-23 06:47:07 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2014-12-21 01:45:10 +01:00
|
|
|
return &ch
|
|
|
|
}
|
|
|
|
|
2014-12-23 06:47:07 +01:00
|
|
|
func (ch *Channel) Close() {
|
2014-12-23 07:54:29 +01:00
|
|
|
ch.users.Each(func(u Item) {
|
|
|
|
u.(*User).Close()
|
|
|
|
})
|
|
|
|
ch.users.Clear()
|
2014-12-23 06:47:07 +01:00
|
|
|
close(ch.broadcast)
|
|
|
|
}
|
|
|
|
|
2014-12-21 01:45:10 +01:00
|
|
|
func (ch *Channel) Send(m Message) {
|
2014-12-21 05:21:41 +01:00
|
|
|
ch.broadcast <- m
|
2014-12-21 01:45:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ch *Channel) Join(u *User) error {
|
|
|
|
err := ch.users.Add(u)
|
2014-12-21 05:21:41 +01:00
|
|
|
if err != nil {
|
2014-12-21 19:17:14 +01:00
|
|
|
return err
|
2014-12-21 05:21:41 +01:00
|
|
|
}
|
2014-12-21 19:17:14 +01:00
|
|
|
s := fmt.Sprintf("%s joined. (Connected: %d)", u.Name(), ch.users.Len())
|
|
|
|
ch.Send(*NewMessage(s))
|
|
|
|
return nil
|
2014-12-21 01:45:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ch *Channel) Leave(u *User) error {
|
|
|
|
err := ch.users.Remove(u)
|
2014-12-21 05:21:41 +01:00
|
|
|
if err != nil {
|
2014-12-21 19:17:14 +01:00
|
|
|
return err
|
2014-12-21 05:21:41 +01:00
|
|
|
}
|
2014-12-21 19:17:14 +01:00
|
|
|
s := fmt.Sprintf("%s left.", u.Name())
|
|
|
|
ch.Send(*NewMessage(s))
|
|
|
|
return nil
|
2014-12-21 01:45:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ch *Channel) Topic() string {
|
|
|
|
return ch.topic
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ch *Channel) SetTopic(s string) {
|
|
|
|
ch.topic = s
|
|
|
|
}
|