diff --git a/irc/capability.go b/irc/capability.go index 40f67143..d2958517 100644 --- a/irc/capability.go +++ b/irc/capability.go @@ -10,7 +10,7 @@ import ( "github.com/DanielOaks/girc-go/ircmsg" ) -// Capabilities are optional features a client may request from a server. +// Capability represents an optional feature that a client may request from the server. type Capability string const ( @@ -33,6 +33,7 @@ const ( ) var ( + // SupportedCapabilities are the caps we advertise. SupportedCapabilities = CapabilitySet{ AccountTag: true, AccountNotify: true, @@ -51,6 +52,7 @@ var ( // STS is set during server startup UserhostInNames: true, } + // CapValues are the actual values we advertise to v3.2 clients. CapValues = map[Capability]string{ SASL: "PLAIN,EXTERNAL", } @@ -60,20 +62,7 @@ func (capability Capability) String() string { return string(capability) } -// CapModifiers are indicators showing the state of a capability after a REQ or -// ACK. -type CapModifier rune - -const ( - Ack CapModifier = '~' - Disable CapModifier = '-' - Sticky CapModifier = '=' -) - -func (mod CapModifier) String() string { - return string(mod) -} - +// CapState shows whether we're negotiating caps, finished, etc for connection registration. type CapState uint const ( @@ -116,8 +105,8 @@ func (set CapabilitySet) DisableString() string { parts := make([]string, len(set)) index := 0 for capability := range set { - parts[index] = Disable.String() + capability.String() - index += 1 + parts[index] = "-" + capability.String() + index++ } return strings.Join(parts, " ") } diff --git a/irc/client_lookup_set.go b/irc/client_lookup_set.go index d2f97ced..8819c23a 100644 --- a/irc/client_lookup_set.go +++ b/irc/client_lookup_set.go @@ -22,10 +22,11 @@ var ( ErrNicknameMismatch = errors.New("nickname mismatch") ) +// ExpandUserHost takes a userhost, and returns an expanded version. func ExpandUserHost(userhost string) (expanded string) { expanded = userhost // fill in missing wildcards for nicks - //TODO(dan): this would fail with dan@lol, do we want to accommodate that? + //TODO(dan): this would fail with dan@lol, fix that. if !strings.Contains(expanded, "!") { expanded += "!*" } @@ -35,17 +36,20 @@ func ExpandUserHost(userhost string) (expanded string) { return } +// ClientLookupSet represents a way to store, search and lookup clients. type ClientLookupSet struct { ByNickMutex sync.RWMutex ByNick map[string]*Client } +// NewClientLookupSet returns a new lookup set. func NewClientLookupSet() *ClientLookupSet { return &ClientLookupSet{ ByNick: make(map[string]*Client), } } +// Count returns how many clients are in the lookup set. func (clients *ClientLookupSet) Count() int { clients.ByNickMutex.RLock() defer clients.ByNickMutex.RUnlock() @@ -53,7 +57,8 @@ func (clients *ClientLookupSet) Count() int { return count } -//TODO(dan): wouldn't it be best to always use Get rather than this? +// Has returns whether or not the given client exists. +//TODO(dan): This seems like ripe ground for a race, if code does Has then Get, and assumes the Get will return a client. func (clients *ClientLookupSet) Has(nick string) bool { casefoldedName, err := CasefoldName(nick) if err == nil { @@ -75,6 +80,7 @@ func (clients *ClientLookupSet) getNoMutex(nick string) *Client { return nil } +// Get retrieves a client from the set, if they exist. func (clients *ClientLookupSet) Get(nick string) *Client { casefoldedName, err := CasefoldName(nick) if err == nil { @@ -86,6 +92,7 @@ func (clients *ClientLookupSet) Get(nick string) *Client { return nil } +// Add adds a client to the lookup set. func (clients *ClientLookupSet) Add(client *Client, nick string) error { nick, err := CasefoldName(nick) if err != nil { @@ -100,6 +107,7 @@ func (clients *ClientLookupSet) Add(client *Client, nick string) error { return nil } +// Remove removes a client from the lookup set. func (clients *ClientLookupSet) Remove(client *Client) error { if !client.HasNick() { return ErrNickMissing @@ -113,6 +121,7 @@ func (clients *ClientLookupSet) Remove(client *Client) error { return nil } +// Replace renames an existing client in the lookup set. func (clients *ClientLookupSet) Replace(oldNick, newNick string, client *Client) error { // get casefolded nicknames oldNick, err := CasefoldName(oldNick) @@ -145,6 +154,7 @@ func (clients *ClientLookupSet) Replace(oldNick, newNick string, client *Client) return nil } +// AllWithCaps returns all clients with the given capabilities. func (clients *ClientLookupSet) AllWithCaps(caps ...Capability) (set ClientSet) { set = make(ClientSet) @@ -165,6 +175,7 @@ func (clients *ClientLookupSet) AllWithCaps(caps ...Capability) (set ClientSet) return set } +// FindAll returns all clients that match the given userhost mask. func (clients *ClientLookupSet) FindAll(userhost string) (set ClientSet) { set = make(ClientSet) @@ -185,6 +196,7 @@ func (clients *ClientLookupSet) FindAll(userhost string) (set ClientSet) { return set } +// Find returns the first client that matches the given userhost mask. func (clients *ClientLookupSet) Find(userhost string) *Client { userhost, err := Casefold(ExpandUserHost(userhost)) if err != nil { diff --git a/irc/message_tags.go b/irc/message_tags.go index b45a67ac..ca9daa34 100644 --- a/irc/message_tags.go +++ b/irc/message_tags.go @@ -5,7 +5,7 @@ package irc import "github.com/DanielOaks/girc-go/ircmsg" -// GetClientOnlyTags tags a tag map, and returns a map containing just the client-only tags from it. +// GetClientOnlyTags takes a tag map and returns a map containing just the client-only tags from it. func GetClientOnlyTags(tags map[string]ircmsg.TagValue) *map[string]ircmsg.TagValue { if len(tags) < 1 { return nil diff --git a/irc/numerics.go b/irc/numerics.go index 0ea3d42b..8a51ba7a 100644 --- a/irc/numerics.go +++ b/irc/numerics.go @@ -5,6 +5,12 @@ package irc +// These numerics have been retrieved from: +// http://defs.ircdocs.horse/ and http://modern.ircdocs.horse/ +// +// They're intended to represent a relatively-standard cross-section of the IRC +// server ecosystem out there. Custom numerics will be marked as such. + const ( RPL_WELCOME = "001" RPL_YOURHOST = "002"