mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-22 03:49:27 +01:00
Implement mode [+-]i.
This commit is contained in:
parent
8f0bd1b07a
commit
99364e8b5f
@ -5,18 +5,19 @@ import (
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
addr net.Addr
|
||||
conn net.Conn
|
||||
send chan<- string
|
||||
recv <-chan string
|
||||
username string
|
||||
realname string
|
||||
nick string
|
||||
registered bool
|
||||
invisible bool
|
||||
}
|
||||
|
||||
func NewClient(conn net.Conn) *Client {
|
||||
client := new(Client)
|
||||
client.addr = conn.RemoteAddr()
|
||||
client.conn = conn
|
||||
client.send = StringWriteChan(conn)
|
||||
client.recv = StringReadChan(conn)
|
||||
return client
|
||||
@ -38,3 +39,10 @@ func (c *Client) Nick() string {
|
||||
}
|
||||
return "<guest>"
|
||||
}
|
||||
|
||||
func (c *Client) UModeString() string {
|
||||
if c.invisible {
|
||||
return "+i"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -1,5 +1,9 @@
|
||||
package irc
|
||||
|
||||
type Message interface {
|
||||
Handle(s *Server, c *Client)
|
||||
}
|
||||
|
||||
func (m *NickMessage) Handle(s *Server, c *Client) {
|
||||
if s.nicks[m.nickname] != nil {
|
||||
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) {
|
||||
c.send <- MessageError()
|
||||
c.conn.Close()
|
||||
delete(s.nicks, c.nick)
|
||||
}
|
||||
|
||||
@ -35,6 +40,21 @@ func (m *PingMessage) Handle(s *Server, c *Client) {
|
||||
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) {
|
||||
if (!c.registered && c.nick != "" && c.username != "") {
|
||||
c.registered = true
|
||||
|
@ -10,6 +10,7 @@ const (
|
||||
RPL_YOURHOST = "002"
|
||||
RPL_CREATED = "003"
|
||||
RPL_MYINFO = "004"
|
||||
RPL_UMODEIS = "221"
|
||||
RPL_NONE = "300"
|
||||
)
|
||||
|
||||
|
@ -1,9 +1,5 @@
|
||||
package irc
|
||||
|
||||
type Message interface {
|
||||
Handle(s *Server, c *Client)
|
||||
}
|
||||
|
||||
type NickMessage struct {
|
||||
nickname string
|
||||
}
|
||||
@ -15,7 +11,6 @@ type UserMessage struct {
|
||||
realname string
|
||||
}
|
||||
|
||||
|
||||
type QuitMessage struct {
|
||||
message string
|
||||
}
|
||||
@ -25,3 +20,8 @@ type UnknownMessage struct {
|
||||
}
|
||||
|
||||
type PingMessage struct {}
|
||||
|
||||
type ModeMessage struct {
|
||||
nickname string
|
||||
modes []string
|
||||
}
|
||||
|
@ -16,12 +16,13 @@ func readTrimmedLine(reader *bufio.Reader) (string, error) {
|
||||
func StringReadChan(conn net.Conn) <-chan string {
|
||||
ch := make(chan string)
|
||||
reader := bufio.NewReader(conn)
|
||||
addr := conn.RemoteAddr()
|
||||
go func() {
|
||||
for {
|
||||
line, err := readTrimmedLine(reader)
|
||||
if (line != "") {
|
||||
ch <- line
|
||||
log.Printf("%s -> %s", conn.RemoteAddr(), line)
|
||||
log.Printf("%s -> %s", addr, line)
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
@ -35,13 +36,14 @@ func StringReadChan(conn net.Conn) <-chan string {
|
||||
func StringWriteChan(conn net.Conn) chan<- string {
|
||||
ch := make(chan string)
|
||||
writer := bufio.NewWriter(conn)
|
||||
addr := conn.RemoteAddr()
|
||||
go func() {
|
||||
for str := range ch {
|
||||
if _, err := writer.WriteString(str + "\r\n"); err != nil {
|
||||
break
|
||||
}
|
||||
writer.Flush()
|
||||
log.Printf("%s <- %s", conn.RemoteAddr(), str)
|
||||
log.Printf("%s <- %s", addr, str)
|
||||
}
|
||||
close(ch)
|
||||
}()
|
||||
|
@ -1,10 +1,33 @@
|
||||
package irc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"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) {
|
||||
if line == "" {
|
||||
return "", ""
|
||||
@ -31,25 +54,6 @@ func parseLine(line string) (string, []string) {
|
||||
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
|
||||
|
||||
@ -86,3 +90,25 @@ func NewUserMessage(args []string) Message {
|
||||
msg.realname = args[3]
|
||||
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
|
||||
}
|
||||
|
@ -17,7 +17,11 @@ func ReplyCreated(nick string, created 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 {
|
||||
@ -32,6 +36,10 @@ func ErrUnknownCommand(nick string, command string) string {
|
||||
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 {
|
||||
return "PONG"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user