Merge pull request #31 from edmund-huber/theater_mode_cleanup

clean up /theater
This commit is contained in:
Jeremy Latt 2014-03-27 14:46:15 -07:00
commit ec3fcc9151
8 changed files with 76 additions and 54 deletions

View File

@ -6,15 +6,14 @@ import (
) )
type Channel struct { type Channel struct {
flags ChannelModeSet flags ChannelModeSet
lists map[ChannelMode]*UserMaskSet lists map[ChannelMode]*UserMaskSet
key Text key Text
members MemberSet members MemberSet
name Name name Name
server *Server server *Server
topic Text topic Text
userLimit uint64 userLimit uint64
theaterUser *Client
} }
// NewChannel creates a new channel from a `Server` and a `name` // NewChannel creates a new channel from a `Server` and a `name`
@ -406,9 +405,6 @@ func (channel *Channel) applyMode(client *Client, change *ChannelModeChange) boo
return channel.applyModeMember(client, change.mode, change.op, return channel.applyModeMember(client, change.mode, change.op,
NewName(change.arg)) NewName(change.arg))
case Theater:
client.ErrConfiguredMode(change.mode)
default: default:
client.ErrUnknownMode(change.mode, channel) client.ErrUnknownMode(change.mode, channel)
} }

View File

@ -13,28 +13,27 @@ const (
) )
type Client struct { type Client struct {
atime time.Time atime time.Time
authorized bool authorized bool
awayMessage Text awayMessage Text
capabilities CapabilitySet capabilities CapabilitySet
capState CapState capState CapState
channels ChannelSet channels ChannelSet
commands chan Command commands chan Command
ctime time.Time ctime time.Time
flags map[UserMode]bool flags map[UserMode]bool
hasQuit bool hasQuit bool
hops uint hops uint
hostname Name hostname Name
idleTimer *time.Timer idleTimer *time.Timer
loginTimer *time.Timer loginTimer *time.Timer
nick Name nick Name
quitTimer *time.Timer quitTimer *time.Timer
realname Text realname Text
registered bool registered bool
server *Server server *Server
socket *Socket socket *Socket
username Name username Name
theaterChannels []*Channel
} }
func NewClient(server *Server, conn net.Conn) *Client { func NewClient(server *Server, conn net.Conn) *Client {
@ -260,10 +259,6 @@ func (client *Client) Quit(message Text) {
return return
} }
for _, channel := range client.theaterChannels {
delete(channel.flags, Theater)
}
client.Reply(RplError("connection closed")) client.Reply(RplError("connection closed"))
client.hasQuit = true client.hasQuit = true
client.server.whoWas.Append(client) client.server.whoWas.Append(client)

View File

@ -966,7 +966,7 @@ func NewTheaterCommand(args []string) (Command, error) {
return &TheaterActionCommand{ return &TheaterActionCommand{
channel: NewName(args[1]), channel: NewName(args[1]),
asNick: NewName(args[2]), asNick: NewName(args[2]),
action: NewText(args[3]), action: NewCTCPText(args[3]),
}, nil }, nil
} else { } else {
return nil, ErrParseCommand return nil, ErrParseCommand

View File

@ -83,7 +83,7 @@ const (
Quiet ChannelMode = 'q' // flag Quiet ChannelMode = 'q' // flag
ReOp ChannelMode = 'r' // flag ReOp ChannelMode = 'r' // flag
Secret ChannelMode = 's' // flag, deprecated Secret ChannelMode = 's' // flag, deprecated
Theater ChannelMode = 'T' // flag arg, nonstandard Theater ChannelMode = 'T' // flag, nonstandard
UserLimit ChannelMode = 'l' // flag arg UserLimit ChannelMode = 'l' // flag arg
Voice ChannelMode = 'v' // arg Voice ChannelMode = 'v' // arg
) )

View File

@ -99,6 +99,10 @@ func RplPrivMsg(source Identifiable, target Identifiable, message Text) string {
return NewStringReply(source, PRIVMSG, "%s :%s", target.Nick(), message) return NewStringReply(source, PRIVMSG, "%s :%s", target.Nick(), message)
} }
func RplCTCPAction(source Identifiable, target Identifiable, action CTCPText) string {
return RplPrivMsg(source, target, NewText(fmt.Sprintf("\x01ACTION %s\x01", action)))
}
func RplNotice(source Identifiable, target Identifiable, message Text) string { func RplNotice(source Identifiable, target Identifiable, message Text) string {
return NewStringReply(source, NOTICE, "%s :%s", target.Nick(), message) return NewStringReply(source, NOTICE, "%s :%s", target.Nick(), message)
} }

View File

@ -64,3 +64,12 @@ func NewText(str string) Text {
func (text Text) String() string { func (text Text) String() string {
return string(text) return string(text)
} }
// CTCPText is text suitably escaped for CTCP.
type CTCPText string
var ctcpEscaper = strings.NewReplacer("\x00", "\x200", "\n", "\x20n", "\r", "\x20r")
func NewCTCPText(str string) CTCPText {
return CTCPText(ctcpEscaper.Replace(str))
}

View File

@ -51,11 +51,12 @@ func (m *TheaterIdentifyCommand) HandleServer(s *Server) {
return return
} }
if channel.theaterUser == nil { if channel.members.AnyHasMode(Theater) {
client.theaterChannels = append(client.theaterChannels, channel) client.Reply(RplNotice(s, client, "someone else is +T in this channel"))
channel.flags[Theater] = true return
channel.theaterUser = client
} }
channel.members[client][Theater] = true
} }
type TheaterPrivMsgCommand struct { type TheaterPrivMsgCommand struct {
@ -71,6 +72,7 @@ func (cmd *TheaterPrivMsgCommand) String() string {
} }
func (m *TheaterPrivMsgCommand) HandleServer(s *Server) { func (m *TheaterPrivMsgCommand) HandleServer(s *Server) {
client := m.Client() client := m.Client()
if !m.channel.IsChannel() { if !m.channel.IsChannel() {
client.ErrNoSuchChannel(m.channel) client.ErrNoSuchChannel(m.channel)
return return
@ -82,10 +84,13 @@ func (m *TheaterPrivMsgCommand) HandleServer(s *Server) {
return return
} }
if channel.theaterUser == client { if !channel.members.HasMode(client, Theater) {
for member := range channel.members { client.Reply(RplNotice(s, client, "you are not +T"))
member.Reply(RplPrivMsg(TheaterClient(m.asNick), channel, m.message)) return
} }
for member := range channel.members {
member.Reply(RplPrivMsg(TheaterClient(m.asNick), channel, m.message))
} }
} }
@ -93,7 +98,7 @@ type TheaterActionCommand struct {
BaseCommand BaseCommand
channel Name channel Name
asNick Name asNick Name
action Text action CTCPText
} }
func (cmd *TheaterActionCommand) String() string { func (cmd *TheaterActionCommand) String() string {
@ -102,7 +107,8 @@ func (cmd *TheaterActionCommand) String() string {
func (m *TheaterActionCommand) HandleServer(s *Server) { func (m *TheaterActionCommand) HandleServer(s *Server) {
client := m.Client() client := m.Client()
if m.channel.IsChannel() {
if !m.channel.IsChannel() {
client.ErrNoSuchChannel(m.channel) client.ErrNoSuchChannel(m.channel)
return return
} }
@ -113,9 +119,12 @@ func (m *TheaterActionCommand) HandleServer(s *Server) {
return return
} }
if channel.theaterUser == client { if !channel.members.HasMode(client, Theater) {
for member := range channel.members { client.Reply(RplNotice(s, client, "you are not +T"))
member.Reply(RplPrivMsg(TheaterClient(m.asNick), channel, NewText(fmt.Sprintf("\001ACTION %s\001", m.action)))) return
} }
for member := range channel.members {
member.Reply(RplCTCPAction(TheaterClient(m.asNick), channel, m.action))
} }
} }

View File

@ -83,6 +83,15 @@ func (members MemberSet) HasMode(member *Client, mode ChannelMode) bool {
return modes[mode] return modes[mode]
} }
func (members MemberSet) AnyHasMode(mode ChannelMode) bool {
for _, modes := range members {
if modes[mode] {
return true
}
}
return false
}
type ChannelSet map[*Channel]bool type ChannelSet map[*Channel]bool
func (channels ChannelSet) Add(channel *Channel) { func (channels ChannelSet) Add(channel *Channel) {