123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- package irc
-
- import (
- "log"
- )
-
- type Channel struct {
- commands chan<- ChannelCommand
- key string
- members ClientSet
- name string
- noOutside bool
- password string
- replies chan<- Reply
- server *Server
- topic string
- }
-
- type ChannelSet map[*Channel]bool
-
- type ChannelCommand interface {
- Command
- HandleChannel(channel *Channel)
- }
-
- // NewChannel creates a new channel from a `Server` and a `name`
- // string, which must be unique on the server.
- func NewChannel(s *Server, name string) *Channel {
- commands := make(chan ChannelCommand)
- replies := make(chan Reply)
- channel := &Channel{
- name: name,
- members: make(ClientSet),
- server: s,
- commands: commands,
- replies: replies,
- }
- go channel.receiveCommands(commands)
- go channel.receiveReplies(replies)
- return channel
- }
-
- func (channel *Channel) receiveCommands(commands <-chan ChannelCommand) {
- for command := range commands {
- if DEBUG_CHANNEL {
- log.Printf("%s → %s : %s", command.Source(), channel, command)
- }
- command.HandleChannel(channel)
- }
- }
-
- func (channel *Channel) receiveReplies(replies <-chan Reply) {
- for reply := range replies {
- if DEBUG_CHANNEL {
- log.Printf("%s ← %s : %s", channel, reply.Source(), reply)
- }
- for client := range channel.members {
- client.replies <- reply
- }
- }
- }
-
- func (channel *Channel) IsEmpty() bool {
- return len(channel.members) == 0
- }
-
- func (channel *Channel) GetTopic(replier Replier) {
- if channel.topic == "" {
- replier.Replies() <- RplNoTopic(channel)
- return
- }
-
- replier.Replies() <- RplTopic(channel)
- }
-
- func (channel *Channel) GetUsers(replier Replier) {
- replier.Replies() <- NewNamesReply(channel)
- }
-
- func (channel *Channel) Nicks() []string {
- nicks := make([]string, len(channel.members))
- i := 0
- for client := range channel.members {
- nicks[i] = client.Nick()
- i += 1
- }
- return nicks
- }
-
- func (channel *Channel) Replies() chan<- Reply {
- return channel.replies
- }
-
- func (channel *Channel) Id() string {
- return channel.name
- }
-
- func (channel *Channel) Nick() string {
- return channel.name
- }
-
- func (channel *Channel) PublicId() string {
- return channel.name
- }
-
- func (channel *Channel) String() string {
- return channel.Id()
- }
-
- func (channel *Channel) Join(client *Client) {
- channel.members[client] = true
- client.channels[channel] = true
- reply := RplJoin(channel, client)
- channel.replies <- reply
- channel.GetTopic(client)
- channel.GetUsers(client)
- }
-
- func (channel *Channel) HasMember(client *Client) bool {
- return channel.members[client]
- }
-
- //
- // commands
- //
-
- func (m *JoinCommand) HandleChannel(channel *Channel) {
- client := m.Client()
- if channel.key != m.channels[channel.name] {
- client.replies <- ErrBadChannelKey(channel)
- return
- }
-
- channel.Join(client)
- }
-
- func (m *PartCommand) HandleChannel(channel *Channel) {
- c := m.Client()
-
- if !channel.HasMember(c) {
- c.replies <- ErrNotOnChannel(channel)
- return
- }
-
- msg := m.message
- if msg == "" {
- msg = c.Nick()
- }
-
- channel.replies <- RplPart(channel, c, msg)
-
- delete(channel.members, c)
- delete(c.channels, channel)
-
- if channel.IsEmpty() { // TODO persistent channels
- channel.server.DeleteChannel(channel)
- }
- }
-
- func (m *TopicCommand) HandleChannel(channel *Channel) {
- client := m.Client()
-
- if !channel.HasMember(client) {
- client.replies <- ErrNotOnChannel(channel)
- return
- }
-
- if m.topic == "" {
- channel.GetTopic(client)
- return
- }
-
- channel.topic = m.topic
-
- channel.GetTopic(channel)
- }
-
- func (m *PrivMsgCommand) HandleChannel(channel *Channel) {
- channel.replies <- RplPrivMsgChannel(channel, m.Client(), m.message)
- }
|