3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-10 22:19:31 +01:00

Implement mode [+-]i.

This commit is contained in:
Jeremy Latt 2012-04-17 20:24:26 -07:00
parent 8f0bd1b07a
commit 99364e8b5f
7 changed files with 94 additions and 29 deletions

View File

@ -5,18 +5,19 @@ import (
) )
type Client struct { type Client struct {
addr net.Addr conn net.Conn
send chan<- string send chan<- string
recv <-chan string recv <-chan string
username string username string
realname string realname string
nick string nick string
registered bool registered bool
invisible bool
} }
func NewClient(conn net.Conn) *Client { func NewClient(conn net.Conn) *Client {
client := new(Client) client := new(Client)
client.addr = conn.RemoteAddr() client.conn = conn
client.send = StringWriteChan(conn) client.send = StringWriteChan(conn)
client.recv = StringReadChan(conn) client.recv = StringReadChan(conn)
return client return client
@ -38,3 +39,10 @@ func (c *Client) Nick() string {
} }
return "<guest>" return "<guest>"
} }
func (c *Client) UModeString() string {
if c.invisible {
return "+i"
}
return ""
}

View File

@ -1,5 +1,9 @@
package irc package irc
type Message interface {
Handle(s *Server, c *Client)
}
func (m *NickMessage) Handle(s *Server, c *Client) { func (m *NickMessage) Handle(s *Server, c *Client) {
if s.nicks[m.nickname] != nil { if s.nicks[m.nickname] != nil {
c.send <- ErrNickNameInUse(m.nickname) c.send <- ErrNickNameInUse(m.nickname)
@ -24,6 +28,7 @@ func (m *UserMessage) Handle(s *Server, c *Client) {
func (m *QuitMessage) Handle(s *Server, c *Client) { func (m *QuitMessage) Handle(s *Server, c *Client) {
c.send <- MessageError() c.send <- MessageError()
c.conn.Close()
delete(s.nicks, c.nick) delete(s.nicks, c.nick)
} }
@ -35,6 +40,21 @@ func (m *PingMessage) Handle(s *Server, c *Client) {
c.send <- MessagePong() c.send <- MessagePong()
} }
func (m *ModeMessage) Handle(s *Server, c *Client) {
if m.nickname != c.nick {
c.send <- ErrUsersDontMatch(c.Nick())
return
}
for _, mode := range m.modes {
if mode == "+i" {
c.invisible = true
} else if mode == "-i" {
c.invisible = false
}
}
c.send <- ReplyUModeIs(c)
}
func tryRegister(s *Server, c *Client) { func tryRegister(s *Server, c *Client) {
if (!c.registered && c.nick != "" && c.username != "") { if (!c.registered && c.nick != "" && c.username != "") {
c.registered = true c.registered = true

View File

@ -10,6 +10,7 @@ const (
RPL_YOURHOST = "002" RPL_YOURHOST = "002"
RPL_CREATED = "003" RPL_CREATED = "003"
RPL_MYINFO = "004" RPL_MYINFO = "004"
RPL_UMODEIS = "221"
RPL_NONE = "300" RPL_NONE = "300"
) )

View File

@ -1,9 +1,5 @@
package irc package irc
type Message interface {
Handle(s *Server, c *Client)
}
type NickMessage struct { type NickMessage struct {
nickname string nickname string
} }
@ -15,7 +11,6 @@ type UserMessage struct {
realname string realname string
} }
type QuitMessage struct { type QuitMessage struct {
message string message string
} }
@ -25,3 +20,8 @@ type UnknownMessage struct {
} }
type PingMessage struct {} type PingMessage struct {}
type ModeMessage struct {
nickname string
modes []string
}

View File

@ -16,12 +16,13 @@ func readTrimmedLine(reader *bufio.Reader) (string, error) {
func StringReadChan(conn net.Conn) <-chan string { func StringReadChan(conn net.Conn) <-chan string {
ch := make(chan string) ch := make(chan string)
reader := bufio.NewReader(conn) reader := bufio.NewReader(conn)
addr := conn.RemoteAddr()
go func() { go func() {
for { for {
line, err := readTrimmedLine(reader) line, err := readTrimmedLine(reader)
if (line != "") { if (line != "") {
ch <- line ch <- line
log.Printf("%s -> %s", conn.RemoteAddr(), line) log.Printf("%s -> %s", addr, line)
} }
if err != nil { if err != nil {
break break
@ -35,13 +36,14 @@ func StringReadChan(conn net.Conn) <-chan string {
func StringWriteChan(conn net.Conn) chan<- string { func StringWriteChan(conn net.Conn) chan<- string {
ch := make(chan string) ch := make(chan string)
writer := bufio.NewWriter(conn) writer := bufio.NewWriter(conn)
addr := conn.RemoteAddr()
go func() { go func() {
for str := range ch { for str := range ch {
if _, err := writer.WriteString(str + "\r\n"); err != nil { if _, err := writer.WriteString(str + "\r\n"); err != nil {
break break
} }
writer.Flush() writer.Flush()
log.Printf("%s <- %s", conn.RemoteAddr(), str) log.Printf("%s <- %s", addr, str)
} }
close(ch) close(ch)
}() }()

View File

@ -1,10 +1,33 @@
package irc package irc
import ( import (
"fmt"
"regexp"
"strconv" "strconv"
"strings" "strings"
) )
var commands = map[string]func([]string) Message {
"MODE": NewModeMessage,
"NICK": NewNickMessage,
"PING": NewPingMessage,
"QUIT": NewQuitMessage,
"USER": NewUserMessage,
}
func ParseMessage(line string) Message {
command, args := parseLine(line)
constructor, ok := commands[command]
var msg Message
if ok {
msg = constructor(args)
}
if msg == nil {
msg = &UnknownMessage{command}
}
return msg
}
func parseArg(line string) (string, string) { func parseArg(line string) (string, string) {
if line == "" { if line == "" {
return "", "" return "", ""
@ -31,25 +54,6 @@ func parseLine(line string) (string, []string) {
return args[0], args[1:] return args[0], args[1:]
} }
var commands = map[string]func([]string) Message {
"NICK": NewNickMessage,
"PING": NewPingMessage,
"QUIT": NewQuitMessage,
"USER": NewUserMessage,
}
func ParseMessage(line string) Message {
command, args := parseLine(line)
constructor, ok := commands[command]
var msg Message
if ok {
msg = constructor(args)
}
if msg == nil {
msg = &UnknownMessage{command}
}
return msg
}
// []string => Message constructors // []string => Message constructors
@ -86,3 +90,25 @@ func NewUserMessage(args []string) Message {
msg.realname = args[3] msg.realname = args[3]
return msg return msg
} }
var MODE_RE = regexp.MustCompile("^[-+][a-zA-Z]+$")
func NewModeMessage(args []string) Message {
if len(args) < 1 {
return nil
}
msg := new(ModeMessage)
msg.nickname = args[0]
for _, arg := range args[1:] {
if !MODE_RE.MatchString(arg) {
// TODO invalid args
return nil
}
prefix := arg[0]
for _, c := range arg[1:] {
mode := fmt.Sprintf("%c%c", prefix, c)
msg.modes = append(msg.modes, mode)
}
}
return msg
}

View File

@ -17,7 +17,11 @@ func ReplyCreated(nick string, created string) string {
} }
func ReplyMyInfo(nick string, servername string) string { func ReplyMyInfo(nick string, servername string) string {
return fmt.Sprintf("%s %s %s %s <user modes> <channel modes>", RPL_MYINFO, nick, servername, VERSION) return fmt.Sprintf("%s %s %s %s i <channel modes>", RPL_MYINFO, nick, servername, VERSION)
}
func ReplyUModeIs(c *Client) string {
return fmt.Sprintf("%s %s %s", RPL_UMODEIS, c.Nick(), c.UModeString())
} }
func ErrAlreadyRegistered(nick string) string { func ErrAlreadyRegistered(nick string) string {
@ -32,6 +36,10 @@ func ErrUnknownCommand(nick string, command string) string {
return fmt.Sprintf("%s %s %s :Unknown command", ERR_UNKNOWNCOMMAND, nick, command) return fmt.Sprintf("%s %s %s :Unknown command", ERR_UNKNOWNCOMMAND, nick, command)
} }
func ErrUsersDontMatch(nick string) string {
return fmt.Sprintf("%s %s :Cannot change mode for other users", ERR_USERSDONTMATCH, nick)
}
func MessagePong() string { func MessagePong() string {
return "PONG" return "PONG"
} }