mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-25 21:39:25 +01:00
Implement mode [+-]i.
This commit is contained in:
parent
8f0bd1b07a
commit
99364e8b5f
@ -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 ""
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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)
|
||||||
}()
|
}()
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user