Very initial RPL_ISUPPORT numeric support

This commit is contained in:
Daniel Oaks 2016-04-12 15:38:42 +10:00
parent aec0b30fc6
commit c88cd328f8
4 changed files with 97 additions and 1 deletions

View File

@ -44,7 +44,8 @@ const (
RPL_YOURHOST NumericCode = 2
RPL_CREATED NumericCode = 3
RPL_MYINFO NumericCode = 4
RPL_BOUNCE NumericCode = 5
RPL_ISUPPORT NumericCode = 5
RPL_BOUNCE NumericCode = 10
RPL_TRACELINK NumericCode = 200
RPL_TRACECONNECTING NumericCode = 201
RPL_TRACEHANDSHAKE NumericCode = 202

66
irc/isupport.go Normal file
View File

@ -0,0 +1,66 @@
package irc
import (
"fmt"
"strings"
)
// ISupportList holds a list of ISUPPORT tokens
type ISupportList struct {
Tokens map[string]*string
CachedReply []string
}
// NewISupportList returns a new ISupportList
func NewISupportList() *ISupportList {
var il ISupportList
il.Tokens = make(map[string]*string)
il.CachedReply = make([]string, 0)
return &il
}
// Add adds an RPL_ISUPPORT token to our internal list
func (il *ISupportList) Add(name string, value string) {
il.Tokens[name] = &value
}
// AddNoValue adds an RPL_ISUPPORT token that does not have a value
func (il *ISupportList) AddNoValue(name string) {
il.Tokens[name] = nil
}
// RegenerateCachedReply regenerates the cached RPL_ISUPPORT reply
func (il *ISupportList) RegenerateCachedReply() {
il.CachedReply = make([]string, 0)
maxlen := 400 // Max length of a single ISUPPORT token line
var length int // Length of the current cache
var cache []string // Token list cache
for name, value := range il.Tokens {
var token string
if value == nil {
token = name
} else {
token = fmt.Sprintf("%s=%s", name, *value)
}
if len(token)+length <= maxlen {
// account for the space separating tokens
if len(cache) > 0 {
length++
}
cache = append(cache, token)
length += len(token)
}
if len(cache) == 13 || len(token)+length >= maxlen {
il.CachedReply = append(il.CachedReply, strings.Join(cache, " "))
cache = make([]string, 0)
length = 0
}
}
if len(cache) > 0 {
il.CachedReply = append(il.CachedReply, strings.Join(cache, " "))
}
}

View File

@ -205,6 +205,14 @@ func (target *Client) RplMyInfo() {
target.server.name, SEM_VER, SupportedUserModes, SupportedChannelModes)
}
func (target *Client) RplISupport() {
for _, tokenline := range target.server.isupport.CachedReply {
target.NumericReply(RPL_ISUPPORT,
"%s :are supported by this server",
tokenline)
}
}
func (target *Client) RplUModeIs(client *Client) {
target.NumericReply(RPL_UMODEIS, client.ModeString())
}

View File

@ -39,6 +39,7 @@ type Server struct {
signals chan os.Signal
whoWas *WhoWasList
theaters map[Name][]byte
isupport *ISupportList
}
var (
@ -79,6 +80,25 @@ func NewServer(config *Config) *Server {
signal.Notify(server.signals, SERVER_SIGNALS...)
// add RPL_ISUPPORT tokens
server.isupport = NewISupportList()
server.isupport.Add("CASEMAPPING", "ascii")
server.isupport.Add("CHANMODES", "") //TODO(dan): Channel mode list here
server.isupport.Add("CHANNELLEN", "") //TODO(dan): Support channel length
server.isupport.Add("CHANTYPES", "#")
server.isupport.Add("EXCEPTS", "")
server.isupport.Add("INVEX", "")
server.isupport.Add("KICKLEN", "") //TODO(dan): Support kick length?
server.isupport.Add("MAXLIST", "") //TODO(dan): Support max list length?
server.isupport.Add("MODES", "") //TODO(dan): Support max modes?
server.isupport.Add("NETWORK", "NetNameHere") //TODO(dan): Support network name
server.isupport.Add("NICKLEN", "") //TODO(dan): Support nick length
server.isupport.Add("PREFIX", "(ov)@+")
server.isupport.Add("STATUSMSG", "@+") //TODO(dan): Autogenerate based on PREFIXes, make sure it's actually supported
server.isupport.Add("TARGMAX", "") //TODO(dan): Support this
server.isupport.Add("TOPICLEN", "") //TODO(dan): Support topic length
server.isupport.RegenerateCachedReply()
return server
}
@ -258,6 +278,7 @@ func (s *Server) tryRegister(c *Client) {
c.RplYourHost()
c.RplCreated()
c.RplMyInfo()
c.RplISupport()
s.MOTD(c)
}