3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-29 15:40:02 +01:00

minimal whois implementation

This commit is contained in:
Jeremy Latt 2014-02-08 17:43:59 -08:00
parent 06648393a1
commit c4f457705a
5 changed files with 81 additions and 23 deletions

View File

@ -88,15 +88,13 @@ func (client *Client) HasUsername() bool {
return client.username != "" return client.username != ""
} }
func (fromClient *Client) InterestedClients() ClientSet { func (client *Client) InterestedClients() ClientSet {
clients := make(ClientSet) clients := make(ClientSet)
clients[fromClient] = true for channel := range client.channels {
for channel := range fromClient.channels { for member := range channel.members {
for client := range channel.members { clients[member] = true
clients[client] = true
} }
} }
return clients return clients
} }

View File

@ -35,6 +35,7 @@ var (
"QUIT": NewQuitCommand, "QUIT": NewQuitCommand,
"TOPIC": NewTopicCommand, "TOPIC": NewTopicCommand,
"USER": NewUserMsgCommand, "USER": NewUserMsgCommand,
"WHOIS": NewWhoisCommand,
} }
) )
@ -451,3 +452,30 @@ func NewModeCommand(args []string) (EditableCommand, error) {
return cmd, nil return cmd, nil
} }
type WhoisCommand struct {
BaseCommand
target string
masks []string
}
func NewWhoisCommand(args []string) (EditableCommand, error) {
if len(args) < 1 {
return nil, NotEnoughArgsError
}
var masks string
var target string
if len(args) > 1 {
target = args[0]
masks = args[1]
} else {
masks = args[0]
}
return &WhoisCommand{
target: target,
masks: strings.Split(masks, ","),
}, nil
}

View File

@ -25,11 +25,11 @@ func StringReadChan(conn net.Conn) <-chan string {
for { for {
line, err := readTrimmedLine(reader) line, err := readTrimmedLine(reader)
if err != nil { if err != nil {
log.Print("net: ", err) log.Printf("%s → %s error: %s", conn.RemoteAddr(), conn.LocalAddr(), err)
break break
} }
if DEBUG_NET { if DEBUG_NET {
log.Printf("%s → %s : %s", conn.RemoteAddr(), conn.LocalAddr(), line) log.Printf("%s → %s %s", conn.RemoteAddr(), conn.LocalAddr(), line)
} }
ch <- line ch <- line
} }
@ -45,10 +45,10 @@ func StringWriteChan(conn net.Conn) chan<- string {
defer close(ch) defer close(ch)
for str := range ch { for str := range ch {
if DEBUG_NET { if DEBUG_NET {
log.Printf("%s ← %s : %s", conn.RemoteAddr(), conn.LocalAddr(), str) log.Printf("%s ← %s %s", conn.RemoteAddr(), conn.LocalAddr(), str)
} }
if _, err := writer.WriteString(str + "\r\n"); err != nil { if _, err := writer.WriteString(str + "\r\n"); err != nil {
log.Print("net: ", err) log.Printf("%s ← %s error: %s", conn.RemoteAddr(), conn.LocalAddr(), err)
break break
} }
writer.Flush() writer.Flush()

View File

@ -6,6 +6,18 @@ import (
"time" "time"
) )
const (
MAX_REPLY_LEN = 510 // 512 - CRLF
)
func joinedLen(names []string) int {
var l = len(names) - 1 // " " between names
for _, name := range names {
l += len(name)
}
return l
}
type Identifier interface { type Identifier interface {
Id() string Id() string
Nick() string Nick() string
@ -96,18 +108,6 @@ func NewNamesReply(channel *Channel) Reply {
} }
} }
const (
MAX_REPLY_LEN = 510 // 512 - CRLF
)
func joinedLen(names []string) int {
var l = len(names) - 1 // " " between names
for _, name := range names {
l += len(name)
}
return l
}
func (reply *NamesReply) Format(client *Client, write chan<- string) { func (reply *NamesReply) Format(client *Client, write chan<- string) {
base := RplNamReply(reply.channel, []string{}) base := RplNamReply(reply.channel, []string{})
baseLen := len(base.FormatString(client)) baseLen := len(base.FormatString(client))
@ -225,6 +225,15 @@ func RplYoureOper(server *Server) Reply {
":You are now an IRC operator") ":You are now an IRC operator")
} }
func RplWhoisUser(server *Server, client *Client) Reply {
return NewNumericReply(server, RPL_WHOISUSER, "%s %s %s * :%s",
client.nick, client.username, client.hostname, client.realname)
}
func RplEndOfWhois(server *Server) Reply {
return NewNumericReply(server, RPL_ENDOFWHOIS, ":End of WHOIS list")
}
// errors (also numeric) // errors (also numeric)
func ErrAlreadyRegistered(source Identifier) Reply { func ErrAlreadyRegistered(source Identifier) Reply {
@ -298,3 +307,7 @@ func ErrNoPrivileges(server *Server) Reply {
func ErrRestricted(server *Server) Reply { func ErrRestricted(server *Server) Reply {
return NewNumericReply(server, ERR_RESTRICTED, ":Your connection is restricted!") return NewNumericReply(server, ERR_RESTRICTED, ":Your connection is restricted!")
} }
func ErrNoSuchServer(server *Server, target string) Reply {
return NewNumericReply(server, ERR_NOSUCHSERVER, "%s :No such server", target)
}

View File

@ -165,6 +165,7 @@ func (m *NickCommand) HandleServer(s *Server) {
} }
reply := RplNick(c, m.nickname) reply := RplNick(c, m.nickname)
c.replies <- reply
for iclient := range c.InterestedClients() { for iclient := range c.InterestedClients() {
iclient.replies <- reply iclient.replies <- reply
} }
@ -201,7 +202,6 @@ func (m *QuitCommand) HandleServer(s *Server) {
reply := RplQuit(c, m.message) reply := RplQuit(c, m.message)
for client := range c.InterestedClients() { for client := range c.InterestedClients() {
client.replies <- reply client.replies <- reply
} }
} }
@ -280,3 +280,22 @@ func (m *ModeCommand) HandleServer(s *Server) {
client.replies <- ErrUsersDontMatch(client) client.replies <- ErrUsersDontMatch(client)
} }
func (m *WhoisCommand) HandleServer(server *Server) {
client := m.Client()
// TODO implement target query
if m.target != "" {
client.replies <- ErrNoSuchServer(server, m.target)
return
}
for _, mask := range m.masks {
// TODO implement wildcard matching
mclient := server.clients[mask]
if mclient != nil {
client.replies <- RplWhoisUser(server, mclient)
}
}
client.replies <- RplEndOfWhois(server)
}