Update vendor (go-irc)

This commit is contained in:
Wim 2017-07-28 14:26:26 +02:00
parent fafd0c68e9
commit 38d09dba2e
9 changed files with 126 additions and 62 deletions

View File

@ -3,13 +3,13 @@ package birc
import ( import (
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"github.com/42wim/go-ircevent"
"github.com/42wim/matterbridge/bridge/config" "github.com/42wim/matterbridge/bridge/config"
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
"github.com/paulrosania/go-charset/charset" "github.com/paulrosania/go-charset/charset"
_ "github.com/paulrosania/go-charset/data" _ "github.com/paulrosania/go-charset/data"
"github.com/saintfish/chardet" "github.com/saintfish/chardet"
ircm "github.com/sorcix/irc" ircm "github.com/sorcix/irc"
"github.com/thoj/go-ircevent"
"io" "io"
"io/ioutil" "io/ioutil"
"regexp" "regexp"

View File

@ -87,6 +87,17 @@ func (irc *Connection) readLoop() {
} }
} }
// Unescape tag values as defined in the IRCv3.2 message tags spec
// http://ircv3.net/specs/core/message-tags-3.2.html
func unescapeTagValue(value string) string {
value = strings.Replace(value, "\\:", ";", -1)
value = strings.Replace(value, "\\s", " ", -1)
value = strings.Replace(value, "\\\\", "\\", -1)
value = strings.Replace(value, "\\r", "\r", -1)
value = strings.Replace(value, "\\n", "\n", -1)
return value
}
//Parse raw irc messages //Parse raw irc messages
func parseToEvent(msg string) (*Event, error) { func parseToEvent(msg string) (*Event, error) {
msg = strings.TrimSuffix(msg, "\n") //Remove \r\n msg = strings.TrimSuffix(msg, "\n") //Remove \r\n
@ -95,6 +106,26 @@ func parseToEvent(msg string) (*Event, error) {
if len(msg) < 5 { if len(msg) < 5 {
return nil, errors.New("Malformed msg from server") return nil, errors.New("Malformed msg from server")
} }
if msg[0] == '@' {
// IRCv3 Message Tags
if i := strings.Index(msg, " "); i > -1 {
event.Tags = make(map[string]string)
tags := strings.Split(msg[1:i], ";")
for _, data := range tags {
parts := strings.SplitN(data, "=", 2)
if len(parts) == 1 {
event.Tags[parts[0]] = ""
} else {
event.Tags[parts[0]] = unescapeTagValue(parts[1])
}
}
msg = msg[i+1 : len(msg)]
} else {
return nil, errors.New("Malformed msg from server")
}
}
if msg[0] == ':' { if msg[0] == ':' {
if i := strings.Index(msg, " "); i > -1 { if i := strings.Index(msg, " "); i > -1 {
event.Source = msg[1:i] event.Source = msg[1:i]
@ -430,26 +461,84 @@ func (irc *Connection) Connect(server string) error {
irc.pwrite <- fmt.Sprintf("PASS %s\r\n", irc.Password) irc.pwrite <- fmt.Sprintf("PASS %s\r\n", irc.Password)
} }
resChan := make(chan *SASLResult) err = irc.negotiateCaps()
if err != nil {
return err
}
irc.pwrite <- fmt.Sprintf("NICK %s\r\n", irc.nick)
irc.pwrite <- fmt.Sprintf("USER %s 0.0.0.0 0.0.0.0 :%s\r\n", irc.user, irc.user)
return nil
}
// Negotiate IRCv3 capabilities
func (irc *Connection) negotiateCaps() error {
saslResChan := make(chan *SASLResult)
if irc.UseSASL {
irc.RequestCaps = append(irc.RequestCaps, "sasl")
irc.setupSASLCallbacks(saslResChan)
}
if len(irc.RequestCaps) == 0 {
return nil
}
cap_chan := make(chan bool, len(irc.RequestCaps))
irc.AddCallback("CAP", func(e *Event) {
if len(e.Arguments) != 3 {
return
}
command := e.Arguments[1]
if command == "LS" {
missing_caps := len(irc.RequestCaps)
for _, cap_name := range strings.Split(e.Arguments[2], " ") {
for _, req_cap := range irc.RequestCaps {
if cap_name == req_cap {
irc.pwrite <- fmt.Sprintf("CAP REQ :%s\r\n", cap_name)
missing_caps--
}
}
}
for i := 0; i < missing_caps; i++ {
cap_chan <- true
}
} else if command == "ACK" || command == "NAK" {
for _, cap_name := range strings.Split(strings.TrimSpace(e.Arguments[2]), " ") {
if cap_name == "" {
continue
}
if command == "ACK" {
irc.AcknowledgedCaps = append(irc.AcknowledgedCaps, cap_name)
}
cap_chan <- true
}
}
})
irc.pwrite <- "CAP LS\r\n"
if irc.UseSASL { if irc.UseSASL {
irc.setupSASLCallbacks(resChan)
irc.pwrite <- fmt.Sprintf("CAP LS\r\n")
// request SASL
irc.pwrite <- fmt.Sprintf("CAP REQ :sasl\r\n")
// if sasl request doesn't complete in 15 seconds, close chan and timeout
select { select {
case res := <-resChan: case res := <-saslResChan:
if res.Failed { if res.Failed {
close(resChan) close(saslResChan)
return res.Err return res.Err
} }
case <-time.After(time.Second * 15): case <-time.After(time.Second * 15):
close(resChan) close(saslResChan)
return errors.New("SASL setup timed out. This shouldn't happen.") return errors.New("SASL setup timed out. This shouldn't happen.")
} }
} }
irc.pwrite <- fmt.Sprintf("NICK %s\r\n", irc.nick)
irc.pwrite <- fmt.Sprintf("USER %s 0.0.0.0 0.0.0.0 :%s\r\n", irc.user, irc.user) // Wait for all capabilities to be ACKed or NAKed before ending negotiation
for i := 0; i < len(irc.RequestCaps); i++ {
<-cap_chan
}
irc.pwrite <- fmt.Sprintf("CAP END\r\n")
return nil return nil
} }

View File

@ -43,7 +43,6 @@ func (irc *Connection) setupSASLCallbacks(result chan<- *SASLResult) {
result <- &SASLResult{true, errors.New(e.Arguments[1])} result <- &SASLResult{true, errors.New(e.Arguments[1])}
}) })
irc.AddCallback("903", func(e *Event) { irc.AddCallback("903", func(e *Event) {
irc.SendRaw("CAP END")
result <- &SASLResult{false, nil} result <- &SASLResult{false, nil}
}) })
irc.AddCallback("904", func(e *Event) { irc.AddCallback("904", func(e *Event) {

View File

@ -15,20 +15,22 @@ import (
type Connection struct { type Connection struct {
sync.Mutex sync.Mutex
sync.WaitGroup sync.WaitGroup
Debug bool Debug bool
Error chan error Error chan error
Password string Password string
UseTLS bool UseTLS bool
UseSASL bool UseSASL bool
SASLLogin string RequestCaps []string
SASLPassword string AcknowledgedCaps []string
SASLMech string SASLLogin string
TLSConfig *tls.Config SASLPassword string
Version string SASLMech string
Timeout time.Duration TLSConfig *tls.Config
PingFreq time.Duration Version string
KeepAlive time.Duration Timeout time.Duration
Server string PingFreq time.Duration
KeepAlive time.Duration
Server string
socket net.Conn socket net.Conn
pwrite chan string pwrite chan string
@ -59,6 +61,7 @@ type Event struct {
Source string //<host> Source string //<host>
User string //<usr> User string //<usr>
Arguments []string Arguments []string
Tags map[string]string
Connection *Connection Connection *Connection
} }

View File

@ -1,27 +0,0 @@
package main
import (
"github.com/thoj/go-ircevent"
"crypto/tls"
"fmt"
)
const channel = "#go-eventirc-test";
const serverssl = "irc.freenode.net:7000"
func main() {
ircnick1 := "blatiblat"
irccon := irc.IRC(ircnick1, "IRCTestSSL")
irccon.VerboseCallbackHandler = true
irccon.Debug = true
irccon.UseTLS = true
irccon.TLSConfig = &tls.Config{InsecureSkipVerify: true}
irccon.AddCallback("001", func(e *irc.Event) { irccon.Join(channel) })
irccon.AddCallback("366", func(e *irc.Event) { })
err := irccon.Connect(serverssl)
if err != nil {
fmt.Printf("Err %s", err )
return
}
irccon.Loop()
}

16
vendor/manifest vendored
View File

@ -1,6 +1,14 @@
{ {
"version": 0, "version": 0,
"dependencies": [ "dependencies": [
{
"importpath": "github.com/42wim/go-ircevent",
"repository": "https://github.com/42wim/go-ircevent",
"vcs": "git",
"revision": "d3aec637ae2f2a4f9ff95df55091894d80fa3112",
"branch": "ircv3",
"notests": true
},
{ {
"importpath": "github.com/BurntSushi/toml", "importpath": "github.com/BurntSushi/toml",
"repository": "https://github.com/BurntSushi/toml", "repository": "https://github.com/BurntSushi/toml",
@ -499,14 +507,6 @@
"branch": "master", "branch": "master",
"notests": true "notests": true
}, },
{
"importpath": "github.com/thoj/go-ircevent",
"repository": "https://github.com/thoj/go-ircevent",
"vcs": "git",
"revision": "1b0acb5f2f1b615cfbd4b9f91abb14cb39a18769",
"branch": "master",
"notests": true
},
{ {
"importpath": "github.com/tylerb/graceful", "importpath": "github.com/tylerb/graceful",
"repository": "https://github.com/tylerb/graceful", "repository": "https://github.com/tylerb/graceful",