mirror of
https://github.com/42wim/matterbridge.git
synced 2024-11-24 03:32:02 -08:00
Update vendor lrstanley/girc and readme
This commit is contained in:
parent
1d414cf2fd
commit
788d3b32ac
@ -175,7 +175,7 @@ Matterbridge wouldn't exist without these libraries:
|
||||
* echo - https://github.com/labstack/echo
|
||||
* gitter - https://github.com/sromku/go-gitter
|
||||
* gops - https://github.com/google/gops
|
||||
* irc - https://github.com/thoj/go-ircevent
|
||||
* irc - https://github.com/lrstanley/girc
|
||||
* mattermost - https://github.com/mattermost/platform
|
||||
* matrix - https://github.com/matrix-org/gomatrix
|
||||
* slack - https://github.com/nlopes/slack
|
||||
|
80
vendor/github.com/lrstanley/girc/builtin.go
generated
vendored
80
vendor/github.com/lrstanley/girc/builtin.go
generated
vendored
@ -16,64 +16,62 @@ func (c *Client) registerBuiltins() {
|
||||
c.Handlers.mu.Lock()
|
||||
|
||||
// Built-in things that should always be supported.
|
||||
c.Handlers.register(true, RPL_WELCOME, HandlerFunc(func(c *Client, e Event) {
|
||||
go handleConnect(c, e)
|
||||
}))
|
||||
c.Handlers.register(true, PING, HandlerFunc(handlePING))
|
||||
c.Handlers.register(true, PONG, HandlerFunc(handlePONG))
|
||||
c.Handlers.register(true, true, RPL_WELCOME, HandlerFunc(handleConnect))
|
||||
c.Handlers.register(true, false, PING, HandlerFunc(handlePING))
|
||||
c.Handlers.register(true, false, PONG, HandlerFunc(handlePONG))
|
||||
|
||||
if !c.Config.disableTracking {
|
||||
// Joins/parts/anything that may add/remove/rename users.
|
||||
c.Handlers.register(true, JOIN, HandlerFunc(handleJOIN))
|
||||
c.Handlers.register(true, PART, HandlerFunc(handlePART))
|
||||
c.Handlers.register(true, KICK, HandlerFunc(handleKICK))
|
||||
c.Handlers.register(true, QUIT, HandlerFunc(handleQUIT))
|
||||
c.Handlers.register(true, NICK, HandlerFunc(handleNICK))
|
||||
c.Handlers.register(true, RPL_NAMREPLY, HandlerFunc(handleNAMES))
|
||||
c.Handlers.register(true, false, JOIN, HandlerFunc(handleJOIN))
|
||||
c.Handlers.register(true, false, PART, HandlerFunc(handlePART))
|
||||
c.Handlers.register(true, false, KICK, HandlerFunc(handleKICK))
|
||||
c.Handlers.register(true, false, QUIT, HandlerFunc(handleQUIT))
|
||||
c.Handlers.register(true, false, NICK, HandlerFunc(handleNICK))
|
||||
c.Handlers.register(true, false, RPL_NAMREPLY, HandlerFunc(handleNAMES))
|
||||
|
||||
// Modes.
|
||||
c.Handlers.register(true, MODE, HandlerFunc(handleMODE))
|
||||
c.Handlers.register(true, RPL_CHANNELMODEIS, HandlerFunc(handleMODE))
|
||||
c.Handlers.register(true, false, MODE, HandlerFunc(handleMODE))
|
||||
c.Handlers.register(true, false, RPL_CHANNELMODEIS, HandlerFunc(handleMODE))
|
||||
|
||||
// WHO/WHOX responses.
|
||||
c.Handlers.register(true, RPL_WHOREPLY, HandlerFunc(handleWHO))
|
||||
c.Handlers.register(true, RPL_WHOSPCRPL, HandlerFunc(handleWHO))
|
||||
c.Handlers.register(true, false, RPL_WHOREPLY, HandlerFunc(handleWHO))
|
||||
c.Handlers.register(true, false, RPL_WHOSPCRPL, HandlerFunc(handleWHO))
|
||||
|
||||
// Other misc. useful stuff.
|
||||
c.Handlers.register(true, TOPIC, HandlerFunc(handleTOPIC))
|
||||
c.Handlers.register(true, RPL_TOPIC, HandlerFunc(handleTOPIC))
|
||||
c.Handlers.register(true, RPL_MYINFO, HandlerFunc(handleMYINFO))
|
||||
c.Handlers.register(true, RPL_ISUPPORT, HandlerFunc(handleISUPPORT))
|
||||
c.Handlers.register(true, RPL_MOTDSTART, HandlerFunc(handleMOTD))
|
||||
c.Handlers.register(true, RPL_MOTD, HandlerFunc(handleMOTD))
|
||||
c.Handlers.register(true, false, TOPIC, HandlerFunc(handleTOPIC))
|
||||
c.Handlers.register(true, false, RPL_TOPIC, HandlerFunc(handleTOPIC))
|
||||
c.Handlers.register(true, false, RPL_MYINFO, HandlerFunc(handleMYINFO))
|
||||
c.Handlers.register(true, false, RPL_ISUPPORT, HandlerFunc(handleISUPPORT))
|
||||
c.Handlers.register(true, false, RPL_MOTDSTART, HandlerFunc(handleMOTD))
|
||||
c.Handlers.register(true, false, RPL_MOTD, HandlerFunc(handleMOTD))
|
||||
|
||||
// Keep users lastactive times up to date.
|
||||
c.Handlers.register(true, PRIVMSG, HandlerFunc(updateLastActive))
|
||||
c.Handlers.register(true, NOTICE, HandlerFunc(updateLastActive))
|
||||
c.Handlers.register(true, TOPIC, HandlerFunc(updateLastActive))
|
||||
c.Handlers.register(true, KICK, HandlerFunc(updateLastActive))
|
||||
c.Handlers.register(true, false, PRIVMSG, HandlerFunc(updateLastActive))
|
||||
c.Handlers.register(true, false, NOTICE, HandlerFunc(updateLastActive))
|
||||
c.Handlers.register(true, false, TOPIC, HandlerFunc(updateLastActive))
|
||||
c.Handlers.register(true, false, KICK, HandlerFunc(updateLastActive))
|
||||
|
||||
// CAP IRCv3-specific tracking and functionality.
|
||||
c.Handlers.register(true, CAP, HandlerFunc(handleCAP))
|
||||
c.Handlers.register(true, CAP_CHGHOST, HandlerFunc(handleCHGHOST))
|
||||
c.Handlers.register(true, CAP_AWAY, HandlerFunc(handleAWAY))
|
||||
c.Handlers.register(true, CAP_ACCOUNT, HandlerFunc(handleACCOUNT))
|
||||
c.Handlers.register(true, ALL_EVENTS, HandlerFunc(handleTags))
|
||||
c.Handlers.register(true, false, CAP, HandlerFunc(handleCAP))
|
||||
c.Handlers.register(true, false, CAP_CHGHOST, HandlerFunc(handleCHGHOST))
|
||||
c.Handlers.register(true, false, CAP_AWAY, HandlerFunc(handleAWAY))
|
||||
c.Handlers.register(true, false, CAP_ACCOUNT, HandlerFunc(handleACCOUNT))
|
||||
c.Handlers.register(true, false, ALL_EVENTS, HandlerFunc(handleTags))
|
||||
|
||||
// SASL IRCv3 support.
|
||||
c.Handlers.register(true, AUTHENTICATE, HandlerFunc(handleSASL))
|
||||
c.Handlers.register(true, RPL_SASLSUCCESS, HandlerFunc(handleSASL))
|
||||
c.Handlers.register(true, RPL_NICKLOCKED, HandlerFunc(handleSASLError))
|
||||
c.Handlers.register(true, ERR_SASLFAIL, HandlerFunc(handleSASLError))
|
||||
c.Handlers.register(true, ERR_SASLTOOLONG, HandlerFunc(handleSASLError))
|
||||
c.Handlers.register(true, ERR_SASLABORTED, HandlerFunc(handleSASLError))
|
||||
c.Handlers.register(true, RPL_SASLMECHS, HandlerFunc(handleSASLError))
|
||||
c.Handlers.register(true, false, AUTHENTICATE, HandlerFunc(handleSASL))
|
||||
c.Handlers.register(true, false, RPL_SASLSUCCESS, HandlerFunc(handleSASL))
|
||||
c.Handlers.register(true, false, RPL_NICKLOCKED, HandlerFunc(handleSASLError))
|
||||
c.Handlers.register(true, false, ERR_SASLFAIL, HandlerFunc(handleSASLError))
|
||||
c.Handlers.register(true, false, ERR_SASLTOOLONG, HandlerFunc(handleSASLError))
|
||||
c.Handlers.register(true, false, ERR_SASLABORTED, HandlerFunc(handleSASLError))
|
||||
c.Handlers.register(true, false, RPL_SASLMECHS, HandlerFunc(handleSASLError))
|
||||
}
|
||||
|
||||
// Nickname collisions.
|
||||
c.Handlers.register(true, ERR_NICKNAMEINUSE, HandlerFunc(nickCollisionHandler))
|
||||
c.Handlers.register(true, ERR_NICKCOLLISION, HandlerFunc(nickCollisionHandler))
|
||||
c.Handlers.register(true, ERR_UNAVAILRESOURCE, HandlerFunc(nickCollisionHandler))
|
||||
c.Handlers.register(true, false, ERR_NICKNAMEINUSE, HandlerFunc(nickCollisionHandler))
|
||||
c.Handlers.register(true, false, ERR_NICKCOLLISION, HandlerFunc(nickCollisionHandler))
|
||||
c.Handlers.register(true, false, ERR_UNAVAILRESOURCE, HandlerFunc(nickCollisionHandler))
|
||||
|
||||
c.Handlers.mu.Unlock()
|
||||
}
|
||||
@ -389,7 +387,7 @@ func handleISUPPORT(c *Client, e Event) {
|
||||
c.state.Lock()
|
||||
// Skip the first parameter, as it's our nickname.
|
||||
for i := 1; i < len(e.Params); i++ {
|
||||
j := strings.IndexByte(e.Params[i], 0x3D) // =
|
||||
j := strings.IndexByte(e.Params[i], '=')
|
||||
|
||||
if j < 1 || (j+1) == len(e.Params[i]) {
|
||||
c.state.serverOptions[e.Params[i]] = ""
|
||||
|
12
vendor/github.com/lrstanley/girc/cap.go
generated
vendored
12
vendor/github.com/lrstanley/girc/cap.go
generated
vendored
@ -375,10 +375,10 @@ func handleTags(c *Client, e Event) {
|
||||
}
|
||||
|
||||
const (
|
||||
prefixTag byte = 0x40 // @
|
||||
prefixTagValue byte = 0x3D // =
|
||||
prefixUserTag byte = 0x2B // +
|
||||
tagSeparator byte = 0x3B // ;
|
||||
prefixTag byte = '@'
|
||||
prefixTagValue byte = '='
|
||||
prefixUserTag byte = '+'
|
||||
tagSeparator byte = ';'
|
||||
maxTagLength int = 511 // 510 + @ and " " (space), though space usually not included.
|
||||
)
|
||||
|
||||
@ -618,7 +618,7 @@ func validTag(name string) bool {
|
||||
|
||||
for i := 0; i < len(name); i++ {
|
||||
// A-Z, a-z, 0-9, -/._
|
||||
if (name[i] < 0x41 || name[i] > 0x5A) && (name[i] < 0x61 || name[i] > 0x7A) && (name[i] < 0x2D || name[i] > 0x39) && name[i] != 0x5F {
|
||||
if (name[i] < 'A' || name[i] > 'Z') && (name[i] < 'a' || name[i] > 'z') && (name[i] < '-' || name[i] > '9') && name[i] != '_' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -631,7 +631,7 @@ func validTag(name string) bool {
|
||||
func validTagValue(value string) bool {
|
||||
for i := 0; i < len(value); i++ {
|
||||
// Don't allow any invisible chars within the tag, or semicolons.
|
||||
if value[i] < 0x21 || value[i] > 0x7E || value[i] == 0x3B {
|
||||
if value[i] < '!' || value[i] > '~' || value[i] == ';' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
44
vendor/github.com/lrstanley/girc/client.go
generated
vendored
44
vendor/github.com/lrstanley/girc/client.go
generated
vendored
@ -464,9 +464,9 @@ func (c *Client) GetHost() string {
|
||||
return c.state.host
|
||||
}
|
||||
|
||||
// Channels returns the active list of channels that the client is in.
|
||||
// ChannelList returns the active list of channel names that the client is in.
|
||||
// Panics if tracking is disabled.
|
||||
func (c *Client) Channels() []string {
|
||||
func (c *Client) ChannelList() []string {
|
||||
c.panicIfNotTracking()
|
||||
|
||||
c.state.RLock()
|
||||
@ -482,9 +482,26 @@ func (c *Client) Channels() []string {
|
||||
return channels
|
||||
}
|
||||
|
||||
// Users returns the active list of users that the client is tracking across
|
||||
// all files. Panics if tracking is disabled.
|
||||
func (c *Client) Users() []string {
|
||||
// Channels returns the active channels that the client is in. Panics if
|
||||
// tracking is disabled.
|
||||
func (c *Client) Channels() []*Channel {
|
||||
c.panicIfNotTracking()
|
||||
|
||||
c.state.RLock()
|
||||
channels := make([]*Channel, len(c.state.channels))
|
||||
var i int
|
||||
for channel := range c.state.channels {
|
||||
channels[i] = c.state.channels[channel].Copy()
|
||||
i++
|
||||
}
|
||||
c.state.RUnlock()
|
||||
|
||||
return channels
|
||||
}
|
||||
|
||||
// UserList returns the active list of nicknames that the client is tracking
|
||||
// across all networks. Panics if tracking is disabled.
|
||||
func (c *Client) UserList() []string {
|
||||
c.panicIfNotTracking()
|
||||
|
||||
c.state.RLock()
|
||||
@ -500,6 +517,23 @@ func (c *Client) Users() []string {
|
||||
return users
|
||||
}
|
||||
|
||||
// Users returns the active users that the client is tracking across all
|
||||
// networks. Panics if tracking is disabled.
|
||||
func (c *Client) Users() []*User {
|
||||
c.panicIfNotTracking()
|
||||
|
||||
c.state.RLock()
|
||||
users := make([]*User, len(c.state.users))
|
||||
var i int
|
||||
for user := range c.state.users {
|
||||
users[i] = c.state.users[user].Copy()
|
||||
i++
|
||||
}
|
||||
c.state.RUnlock()
|
||||
|
||||
return users
|
||||
}
|
||||
|
||||
// LookupChannel looks up a given channel in state. If the channel doesn't
|
||||
// exist, nil is returned. Panics if tracking is disabled.
|
||||
func (c *Client) LookupChannel(name string) *Channel {
|
||||
|
21
vendor/github.com/lrstanley/girc/commands.go
generated
vendored
21
vendor/github.com/lrstanley/girc/commands.go
generated
vendored
@ -272,6 +272,27 @@ func (cmd *Commands) Kick(channel, user, reason string) {
|
||||
cmd.c.Send(&Event{Command: KICK, Params: []string{channel, user}})
|
||||
}
|
||||
|
||||
// Ban adds the +b mode on the given mask on a channel.
|
||||
func (cmd *Commands) Ban(channel, mask string) {
|
||||
cmd.Mode(channel, "+b", mask)
|
||||
}
|
||||
|
||||
// Unban removes the +b mode on the given mask on a channel.
|
||||
func (cmd *Commands) Unban(channel, mask string) {
|
||||
cmd.Mode(channel, "-b", mask)
|
||||
}
|
||||
|
||||
// Mode sends a mode change to the server which should be applied to target
|
||||
// (usually a channel or user), along with a set of modes (generally "+m",
|
||||
// "+mmmm", or "-m", where "m" is the mode you want to change). Params is only
|
||||
// needed if the mode change requires a parameter (ban or invite-only exclude.)
|
||||
func (cmd *Commands) Mode(target, modes string, params ...string) {
|
||||
out := []string{target, modes}
|
||||
out = append(out, params...)
|
||||
|
||||
cmd.c.Send(&Event{Command: MODE, Params: out})
|
||||
}
|
||||
|
||||
// Invite sends a INVITE query to the server, to invite nick to channel.
|
||||
func (cmd *Commands) Invite(channel string, users ...string) {
|
||||
for i := 0; i < len(users); i++ {
|
||||
|
6
vendor/github.com/lrstanley/girc/ctcp.go
generated
vendored
6
vendor/github.com/lrstanley/girc/ctcp.go
generated
vendored
@ -58,7 +58,7 @@ func decodeCTCP(e *Event) *CTCPEvent {
|
||||
if s < 0 {
|
||||
for i := 0; i < len(text); i++ {
|
||||
// Check for A-Z, 0-9.
|
||||
if (text[i] < 0x41 || text[i] > 0x5A) && (text[i] < 0x30 || text[i] > 0x39) {
|
||||
if (text[i] < 'A' || text[i] > 'Z') && (text[i] < '0' || text[i] > '9') {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -74,7 +74,7 @@ func decodeCTCP(e *Event) *CTCPEvent {
|
||||
// Loop through checking the tag first.
|
||||
for i := 0; i < s; i++ {
|
||||
// Check for A-Z, 0-9.
|
||||
if (text[i] < 0x41 || text[i] > 0x5A) && (text[i] < 0x30 || text[i] > 0x39) {
|
||||
if (text[i] < 'A' || text[i] > 'Z') && (text[i] < '0' || text[i] > '9') {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -168,7 +168,7 @@ func (c *CTCP) parseCMD(cmd string) string {
|
||||
|
||||
for i := 0; i < len(cmd); i++ {
|
||||
// Check for A-Z, 0-9.
|
||||
if (cmd[i] < 0x41 || cmd[i] > 0x5A) && (cmd[i] < 0x30 || cmd[i] > 0x39) {
|
||||
if (cmd[i] < 'A' || cmd[i] > 'Z') && (cmd[i] < '0' || cmd[i] > '9') {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
10
vendor/github.com/lrstanley/girc/event.go
generated
vendored
10
vendor/github.com/lrstanley/girc/event.go
generated
vendored
@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
eventSpace byte = 0x20 // Separator.
|
||||
eventSpace byte = ' ' // Separator.
|
||||
maxLength = 510 // Maximum length is 510 (2 for line endings).
|
||||
)
|
||||
|
||||
@ -256,7 +256,7 @@ func (e *Event) Bytes() []byte {
|
||||
|
||||
// Strip newlines and carriage returns.
|
||||
for i := 0; i < len(out); i++ {
|
||||
if out[i] == 0x0A || out[i] == 0x0D {
|
||||
if out[i] == '\n' || out[i] == '\r' {
|
||||
out = append(out[:i], out[i+1:]...)
|
||||
i-- // Decrease the index so we can pick up where we left off.
|
||||
}
|
||||
@ -432,9 +432,9 @@ func (e *Event) StripAction() string {
|
||||
}
|
||||
|
||||
const (
|
||||
messagePrefix byte = 0x3A // ":" -- prefix or last argument
|
||||
prefixIdent byte = 0x21 // "!" -- username
|
||||
prefixHost byte = 0x40 // "@" -- hostname
|
||||
messagePrefix byte = ':' // Prefix or last argument.
|
||||
prefixIdent byte = '!' // Username.
|
||||
prefixHost byte = '@' // Hostname.
|
||||
)
|
||||
|
||||
// Source represents the sender of an IRC event, see RFC1459 section 2.3.1.
|
||||
|
43
vendor/github.com/lrstanley/girc/format.go
generated
vendored
43
vendor/github.com/lrstanley/girc/format.go
generated
vendored
@ -12,8 +12,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
fmtOpenChar = 0x7B // {
|
||||
fmtCloseChar = 0x7D // }
|
||||
fmtOpenChar = '{'
|
||||
fmtCloseChar = '}'
|
||||
)
|
||||
|
||||
var fmtColors = map[string]int{
|
||||
@ -113,7 +113,7 @@ func Fmt(text string) string {
|
||||
|
||||
if last > -1 {
|
||||
// A-Z, a-z, and ","
|
||||
if text[i] != 0x2c && (text[i] <= 0x41 || text[i] >= 0x5a) && (text[i] <= 0x61 || text[i] >= 0x7a) {
|
||||
if text[i] != ',' && (text[i] <= 'A' || text[i] >= 'Z') && (text[i] <= 'a' || text[i] >= 'z') {
|
||||
last = -1
|
||||
continue
|
||||
}
|
||||
@ -127,10 +127,10 @@ func Fmt(text string) string {
|
||||
// See Fmt() for more information.
|
||||
func TrimFmt(text string) string {
|
||||
for color := range fmtColors {
|
||||
text = strings.Replace(text, "{"+color+"}", "", -1)
|
||||
text = strings.Replace(text, string(fmtOpenChar)+color+string(fmtCloseChar), "", -1)
|
||||
}
|
||||
for code := range fmtCodes {
|
||||
text = strings.Replace(text, "{"+code+"}", "", -1)
|
||||
text = strings.Replace(text, string(fmtOpenChar)+code+string(fmtCloseChar), "", -1)
|
||||
}
|
||||
|
||||
return text
|
||||
@ -175,9 +175,10 @@ func IsValidChannel(channel string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// #, +, !<channelid>, or &
|
||||
// Including "*" in the prefix list, as this is commonly used (e.g. ZNC)
|
||||
if bytes.IndexByte([]byte{0x21, 0x23, 0x26, 0x2A, 0x2B}, channel[0]) == -1 {
|
||||
// #, +, !<channelid>, ~, or &
|
||||
// Including "*" and "~" in the prefix list, as these are commonly used
|
||||
// (e.g. ZNC.)
|
||||
if bytes.IndexByte([]byte{'!', '#', '&', '*', '~', '+'}, channel[0]) == -1 {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -186,14 +187,14 @@ func IsValidChannel(channel string) bool {
|
||||
// 1 (prefix) + 5 (id) + 1 (+, channel name)
|
||||
// On some networks, this may be extended with ISUPPORT capabilities,
|
||||
// however this is extremely uncommon.
|
||||
if channel[0] == 0x21 {
|
||||
if channel[0] == '!' {
|
||||
if len(channel) < 7 {
|
||||
return false
|
||||
}
|
||||
|
||||
// check for valid ID
|
||||
for i := 1; i < 6; i++ {
|
||||
if (channel[i] < 0x30 || channel[i] > 0x39) && (channel[i] < 0x41 || channel[i] > 0x5A) {
|
||||
if (channel[i] < '0' || channel[i] > '9') && (channel[i] < 'A' || channel[i] > 'Z') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -222,18 +223,15 @@ func IsValidNick(nick string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
nick = ToRFC1459(nick)
|
||||
|
||||
// Check the first index. Some characters aren't allowed for the first
|
||||
// index of an IRC nickname.
|
||||
if nick[0] < 0x41 || nick[0] > 0x7D {
|
||||
// a-z, A-Z, and _\[]{}^|
|
||||
if (nick[0] < 'A' || nick[0] > '}') && nick[0] != '?' {
|
||||
// a-z, A-Z, '_\[]{}^|', and '?' in the case of znc.
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 1; i < len(nick); i++ {
|
||||
if (nick[i] < 0x41 || nick[i] > 0x7E) && (nick[i] < 0x30 || nick[i] > 0x39) && nick[i] != 0x2D {
|
||||
fmt.Println(nick[i], i, nick)
|
||||
if (nick[i] < 'A' || nick[i] > '}') && (nick[i] < '0' || nick[i] > '9') && nick[i] != '-' {
|
||||
// a-z, A-Z, 0-9, -, and _\[]{}^|
|
||||
return false
|
||||
}
|
||||
@ -262,10 +260,8 @@ func IsValidUser(name string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
name = ToRFC1459(name)
|
||||
|
||||
// "~" is prepended (commonly) if there was no ident server response.
|
||||
if name[0] == 0x7E {
|
||||
if name[0] == '~' {
|
||||
// Means name only contained "~".
|
||||
if len(name) < 2 {
|
||||
return false
|
||||
@ -275,12 +271,12 @@ func IsValidUser(name string) bool {
|
||||
}
|
||||
|
||||
// Check to see if the first index is alphanumeric.
|
||||
if (name[0] < 0x41 || name[0] > 0x4A) && (name[0] < 0x61 || name[0] > 0x7A) && (name[0] < 0x30 || name[0] > 0x39) {
|
||||
if (name[0] < 'A' || name[0] > 'J') && (name[0] < 'a' || name[0] > 'z') && (name[0] < '0' || name[0] > '9') {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 1; i < len(name); i++ {
|
||||
if (name[i] < 0x41 || name[i] > 0x7D) && (name[i] < 0x30 || name[i] > 0x39) && name[i] != 0x2D && name[i] != 0x2E {
|
||||
if (name[i] < 'A' || name[i] > '}') && (name[i] < '0' || name[i] > '9') && name[i] != '-' && name[i] != '.' {
|
||||
// a-z, A-Z, 0-9, -, and _\[]{}^|
|
||||
return false
|
||||
}
|
||||
@ -291,7 +287,10 @@ func IsValidUser(name string) bool {
|
||||
|
||||
// ToRFC1459 converts a string to the stripped down conversion within RFC
|
||||
// 1459. This will do things like replace an "A" with an "a", "[]" with "{}",
|
||||
// and so forth. Useful to compare two nicknames or channels.
|
||||
// and so forth. Useful to compare two nicknames or channels. Note that this
|
||||
// should not be used to normalize nicknames or similar, as this may convert
|
||||
// valid input characters to non-rfc-valid characters. As such, it's main use
|
||||
// is for comparing two nicks.
|
||||
func ToRFC1459(input string) string {
|
||||
var out string
|
||||
|
||||
|
119
vendor/github.com/lrstanley/girc/handler.go
generated
vendored
119
vendor/github.com/lrstanley/girc/handler.go
generated
vendored
@ -29,11 +29,12 @@ func (c *Client) RunHandlers(event *Event) {
|
||||
}
|
||||
}
|
||||
|
||||
// Regular wildcard handlers.
|
||||
c.Handlers.exec(ALL_EVENTS, c, event.Copy())
|
||||
// Background handlers first.
|
||||
c.Handlers.exec(ALL_EVENTS, true, c, event.Copy())
|
||||
c.Handlers.exec(event.Command, true, c, event.Copy())
|
||||
|
||||
// Then regular handlers.
|
||||
c.Handlers.exec(event.Command, c, event.Copy())
|
||||
c.Handlers.exec(ALL_EVENTS, false, c, event.Copy())
|
||||
c.Handlers.exec(event.Command, false, c, event.Copy())
|
||||
|
||||
// Check if it's a CTCP.
|
||||
if ctcp := decodeCTCP(event.Copy()); ctcp != nil {
|
||||
@ -144,7 +145,7 @@ func (c *Caller) cuid(cmd string, n int) (cuid, uid string) {
|
||||
// cuidToID allows easy mapping between a generated cuid and the caller
|
||||
// external/internal handler maps.
|
||||
func (c *Caller) cuidToID(input string) (cmd, uid string) {
|
||||
i := strings.IndexByte(input, 0x3A)
|
||||
i := strings.IndexByte(input, ':')
|
||||
if i < 0 {
|
||||
return "", ""
|
||||
}
|
||||
@ -160,9 +161,9 @@ type execStack struct {
|
||||
// exec executes all handlers pertaining to specified event. Internal first,
|
||||
// then external.
|
||||
//
|
||||
// Please note that there is no specific order/priority for which the
|
||||
// handler types themselves or the handlers are executed.
|
||||
func (c *Caller) exec(command string, client *Client, event *Event) {
|
||||
// Please note that there is no specific order/priority for which the handlers
|
||||
// are executed.
|
||||
func (c *Caller) exec(command string, bg bool, client *Client, event *Event) {
|
||||
// Build a stack of handlers which can be executed concurrently.
|
||||
var stack []execStack
|
||||
|
||||
@ -170,13 +171,21 @@ func (c *Caller) exec(command string, client *Client, event *Event) {
|
||||
// Get internal handlers first.
|
||||
if _, ok := c.internal[command]; ok {
|
||||
for cuid := range c.internal[command] {
|
||||
if (strings.HasSuffix(cuid, ":bg") && !bg) || (!strings.HasSuffix(cuid, ":bg") && bg) {
|
||||
continue
|
||||
}
|
||||
|
||||
stack = append(stack, execStack{c.internal[command][cuid], cuid})
|
||||
}
|
||||
}
|
||||
|
||||
// Aaand then external handlers.
|
||||
// Then external handlers.
|
||||
if _, ok := c.external[command]; ok {
|
||||
for cuid := range c.external[command] {
|
||||
if (strings.HasSuffix(cuid, ":bg") && !bg) || (!strings.HasSuffix(cuid, ":bg") && bg) {
|
||||
continue
|
||||
}
|
||||
|
||||
stack = append(stack, execStack{c.external[command][cuid], cuid})
|
||||
}
|
||||
}
|
||||
@ -189,18 +198,29 @@ func (c *Caller) exec(command string, client *Client, event *Event) {
|
||||
wg.Add(len(stack))
|
||||
for i := 0; i < len(stack); i++ {
|
||||
go func(index int) {
|
||||
c.debug.Printf("executing handler %s for event %s (%d of %d)", stack[index].cuid, command, index+1, len(stack))
|
||||
defer wg.Done()
|
||||
c.debug.Printf("[%d/%d] exec %s => %s", index+1, len(stack), stack[index].cuid, command)
|
||||
start := time.Now()
|
||||
|
||||
// If they want to catch any panics, add to defer stack.
|
||||
if bg {
|
||||
go func() {
|
||||
if client.Config.RecoverFunc != nil {
|
||||
defer recoverHandlerPanic(client, event, stack[index].cuid, 3)
|
||||
}
|
||||
|
||||
stack[index].Execute(client, *event)
|
||||
c.debug.Printf("[%d/%d] done %s == %s", index+1, len(stack), stack[index].cuid, time.Since(start))
|
||||
}()
|
||||
|
||||
c.debug.Printf("execution of %s took %s (%d of %d)", stack[index].cuid, time.Since(start), index+1, len(stack))
|
||||
wg.Done()
|
||||
return
|
||||
}
|
||||
|
||||
if client.Config.RecoverFunc != nil {
|
||||
defer recoverHandlerPanic(client, event, stack[index].cuid, 3)
|
||||
}
|
||||
|
||||
stack[index].Execute(client, *event)
|
||||
c.debug.Printf("[%d/%d] done %s == %s", index+1, len(stack), stack[index].cuid, time.Since(start))
|
||||
}(i)
|
||||
}
|
||||
|
||||
@ -281,9 +301,9 @@ func (c *Caller) remove(cuid string) (success bool) {
|
||||
|
||||
// sregister is much like Caller.register(), except that it safely locks
|
||||
// the Caller mutex.
|
||||
func (c *Caller) sregister(internal bool, cmd string, handler Handler) (cuid string) {
|
||||
func (c *Caller) sregister(internal, bg bool, cmd string, handler Handler) (cuid string) {
|
||||
c.mu.Lock()
|
||||
cuid = c.register(internal, cmd, handler)
|
||||
cuid = c.register(internal, bg, cmd, handler)
|
||||
c.mu.Unlock()
|
||||
|
||||
return cuid
|
||||
@ -291,30 +311,34 @@ func (c *Caller) sregister(internal bool, cmd string, handler Handler) (cuid str
|
||||
|
||||
// register will register a handler in the internal tracker. Unsafe (you
|
||||
// must lock c.mu yourself!)
|
||||
func (c *Caller) register(internal bool, cmd string, handler Handler) (cuid string) {
|
||||
func (c *Caller) register(internal, bg bool, cmd string, handler Handler) (cuid string) {
|
||||
var uid string
|
||||
|
||||
cmd = strings.ToUpper(cmd)
|
||||
|
||||
cuid, uid = c.cuid(cmd, 20)
|
||||
if bg {
|
||||
uid += ":bg"
|
||||
cuid += ":bg"
|
||||
}
|
||||
|
||||
if internal {
|
||||
if _, ok := c.internal[cmd]; !ok {
|
||||
c.internal[cmd] = map[string]Handler{}
|
||||
}
|
||||
|
||||
cuid, uid = c.cuid(cmd, 20)
|
||||
c.internal[cmd][uid] = handler
|
||||
} else {
|
||||
if _, ok := c.external[cmd]; !ok {
|
||||
c.external[cmd] = map[string]Handler{}
|
||||
}
|
||||
|
||||
cuid, uid = c.cuid(cmd, 20)
|
||||
c.external[cmd][uid] = handler
|
||||
}
|
||||
|
||||
_, file, line, _ := runtime.Caller(3)
|
||||
|
||||
c.debug.Printf("registering handler for %q with cuid %q (internal: %t) from: %s:%d", cmd, cuid, internal, file, line)
|
||||
c.debug.Printf("reg %q => %s [int:%t bg:%t] %s:%d", uid, cmd, internal, bg, file, line)
|
||||
|
||||
return cuid
|
||||
}
|
||||
@ -323,31 +347,20 @@ func (c *Caller) register(internal bool, cmd string, handler Handler) (cuid stri
|
||||
// given event. cuid is the handler uid which can be used to remove the
|
||||
// handler with Caller.Remove().
|
||||
func (c *Caller) AddHandler(cmd string, handler Handler) (cuid string) {
|
||||
return c.sregister(false, cmd, handler)
|
||||
return c.sregister(false, false, cmd, handler)
|
||||
}
|
||||
|
||||
// Add registers the handler function for the given event. cuid is the
|
||||
// handler uid which can be used to remove the handler with Caller.Remove().
|
||||
func (c *Caller) Add(cmd string, handler func(client *Client, event Event)) (cuid string) {
|
||||
return c.sregister(false, cmd, HandlerFunc(handler))
|
||||
return c.sregister(false, false, cmd, HandlerFunc(handler))
|
||||
}
|
||||
|
||||
// AddBg registers the handler function for the given event and executes it
|
||||
// in a go-routine. cuid is the handler uid which can be used to remove the
|
||||
// handler with Caller.Remove().
|
||||
func (c *Caller) AddBg(cmd string, handler func(client *Client, event Event)) (cuid string) {
|
||||
return c.sregister(false, cmd, HandlerFunc(func(client *Client, event Event) {
|
||||
// Setting up background-based handlers this way allows us to get
|
||||
// clean call stacks for use with panic recovery.
|
||||
go func() {
|
||||
// If they want to catch any panics, add to defer stack.
|
||||
if client.Config.RecoverFunc != nil {
|
||||
defer recoverHandlerPanic(client, &event, "goroutine", 3)
|
||||
}
|
||||
|
||||
handler(client, event)
|
||||
}()
|
||||
}))
|
||||
return c.sregister(false, true, cmd, HandlerFunc(handler))
|
||||
}
|
||||
|
||||
// AddTmp adds a "temporary" handler, which is good for one-time or few-time
|
||||
@ -361,47 +374,37 @@ func (c *Caller) AddBg(cmd string, handler func(client *Client, event Event)) (c
|
||||
//
|
||||
// Additionally, AddTmp has a useful option, deadline. When set to greater
|
||||
// than 0, deadline will be the amount of time that passes before the handler
|
||||
// is removed from the stack, regardless if the handler returns true or not.
|
||||
// is removed from the stack, regardless of if the handler returns true or not.
|
||||
// This is useful in that it ensures that the handler is cleaned up if the
|
||||
// server does not respond appropriately, or takes too long to respond.
|
||||
//
|
||||
// Note that handlers supplied with AddTmp are executed in a goroutine to
|
||||
// ensure that they are not blocking other handlers. Additionally, use cuid
|
||||
// with Caller.Remove() to prematurely remove the handler from the stack,
|
||||
// bypassing the timeout or waiting for the handler to return that it wants
|
||||
// to be removed from the stack.
|
||||
// ensure that they are not blocking other handlers. However, if you are
|
||||
// creating a temporary handler from another handler, it should be a
|
||||
// background handler.
|
||||
//
|
||||
// Use cuid with Caller.Remove() to prematurely remove the handler from the
|
||||
// stack, bypassing the timeout or waiting for the handler to return that it
|
||||
// wants to be removed from the stack.
|
||||
func (c *Caller) AddTmp(cmd string, deadline time.Duration, handler func(client *Client, event Event) bool) (cuid string, done chan struct{}) {
|
||||
var uid string
|
||||
cuid, uid = c.cuid(cmd, 20)
|
||||
|
||||
done = make(chan struct{})
|
||||
|
||||
c.mu.Lock()
|
||||
if _, ok := c.external[cmd]; !ok {
|
||||
c.external[cmd] = map[string]Handler{}
|
||||
}
|
||||
c.external[cmd][uid] = HandlerFunc(func(client *Client, event Event) {
|
||||
// Setting up background-based handlers this way allows us to get
|
||||
// clean call stacks for use with panic recovery.
|
||||
go func() {
|
||||
// If they want to catch any panics, add to defer stack.
|
||||
if client.Config.RecoverFunc != nil {
|
||||
defer recoverHandlerPanic(client, &event, "tmp-goroutine", 3)
|
||||
}
|
||||
|
||||
cuid = c.sregister(false, true, cmd, HandlerFunc(func(client *Client, event Event) {
|
||||
remove := handler(client, event)
|
||||
if remove {
|
||||
if ok := c.Remove(cuid); ok {
|
||||
close(done)
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
c.mu.Unlock()
|
||||
}))
|
||||
|
||||
if deadline > 0 {
|
||||
go func() {
|
||||
<-time.After(deadline)
|
||||
select {
|
||||
case <-time.After(deadline):
|
||||
case <-done:
|
||||
}
|
||||
|
||||
if ok := c.Remove(cuid); ok {
|
||||
close(done)
|
||||
}
|
||||
|
10
vendor/github.com/lrstanley/girc/modes.go
generated
vendored
10
vendor/github.com/lrstanley/girc/modes.go
generated
vendored
@ -206,11 +206,11 @@ func (c *CModes) Parse(flags string, args []string) (out []CMode) {
|
||||
var argCount int
|
||||
|
||||
for i := 0; i < len(flags); i++ {
|
||||
if flags[i] == 0x2B {
|
||||
if flags[i] == '+' {
|
||||
add = true
|
||||
continue
|
||||
}
|
||||
if flags[i] == 0x2D {
|
||||
if flags[i] == '-' {
|
||||
add = false
|
||||
continue
|
||||
}
|
||||
@ -265,7 +265,7 @@ func IsValidChannelMode(raw string) bool {
|
||||
|
||||
for i := 0; i < len(raw); i++ {
|
||||
// Allowed are: ",", A-Z and a-z.
|
||||
if raw[i] != 0x2C && (raw[i] < 0x41 || raw[i] > 0x5A) && (raw[i] < 0x61 || raw[i] > 0x7A) {
|
||||
if raw[i] != ',' && (raw[i] < 'A' || raw[i] > 'Z') && (raw[i] < 'a' || raw[i] > 'z') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -279,7 +279,7 @@ func isValidUserPrefix(raw string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if raw[0] != 0x28 { // (.
|
||||
if raw[0] != '(' {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -288,7 +288,7 @@ func isValidUserPrefix(raw string) bool {
|
||||
|
||||
// Skip the first one as we know it's (.
|
||||
for i := 1; i < len(raw); i++ {
|
||||
if raw[i] == 0x29 { // ).
|
||||
if raw[i] == ')' {
|
||||
passedKeys = true
|
||||
continue
|
||||
}
|
||||
|
2
vendor/manifest
vendored
2
vendor/manifest
vendored
@ -282,7 +282,7 @@
|
||||
"importpath": "github.com/lrstanley/girc",
|
||||
"repository": "https://github.com/lrstanley/girc",
|
||||
"vcs": "git",
|
||||
"revision": "e698f0468e166574e122130ffd2f579aba7e2abc",
|
||||
"revision": "5dff93b5453c1b2ac8382c9a38881635f47bba0e",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user