Sync matterbridge/go-xmpp with upstream
This commit is contained in:
parent
092ca1cd67
commit
a30bb8fed0
2
go.mod
2
go.mod
|
@ -24,7 +24,7 @@ require (
|
||||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d
|
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d
|
||||||
github.com/matterbridge/discordgo v0.18.1-0.20200308151012-aa40f01cbcc3
|
github.com/matterbridge/discordgo v0.18.1-0.20200308151012-aa40f01cbcc3
|
||||||
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible
|
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible
|
||||||
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91
|
github.com/matterbridge/go-xmpp v0.0.0-20200328215643-8d36ff2c85d1
|
||||||
github.com/matterbridge/gomatrix v0.0.0-20200209224845-c2104d7936a6
|
github.com/matterbridge/gomatrix v0.0.0-20200209224845-c2104d7936a6
|
||||||
github.com/matterbridge/gozulipbot v0.0.0-20190212232658-7aa251978a18
|
github.com/matterbridge/gozulipbot v0.0.0-20190212232658-7aa251978a18
|
||||||
github.com/matterbridge/logrus-prefixed-formatter v0.0.0-20180806162718-01618749af61
|
github.com/matterbridge/logrus-prefixed-formatter v0.0.0-20180806162718-01618749af61
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -130,8 +130,8 @@ github.com/matterbridge/discordgo v0.18.1-0.20200308151012-aa40f01cbcc3 h1:VP/DN
|
||||||
github.com/matterbridge/discordgo v0.18.1-0.20200308151012-aa40f01cbcc3/go.mod h1:5a1bHtG/38ofcx9cgwM5eTW/Pl4SpbQksNDnTRcGA2Y=
|
github.com/matterbridge/discordgo v0.18.1-0.20200308151012-aa40f01cbcc3/go.mod h1:5a1bHtG/38ofcx9cgwM5eTW/Pl4SpbQksNDnTRcGA2Y=
|
||||||
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible h1:oaOqwbg5HxHRxvAbd84ks0Okwoc1ISyUZ87EiVJFhGI=
|
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible h1:oaOqwbg5HxHRxvAbd84ks0Okwoc1ISyUZ87EiVJFhGI=
|
||||||
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible/go.mod h1:igE6rUAn3jai2wCdsjFHfhUoekjrFthoEjFObKKwSb4=
|
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible/go.mod h1:igE6rUAn3jai2wCdsjFHfhUoekjrFthoEjFObKKwSb4=
|
||||||
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91 h1:KzDEcy8eDbTx881giW8a6llsAck3e2bJvMyKvh1IK+k=
|
github.com/matterbridge/go-xmpp v0.0.0-20200328215643-8d36ff2c85d1 h1:1GBtdv3HbYTPbGP3y/QpJ7S4ogB5gs/+gGKhj4ri2CM=
|
||||||
github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91/go.mod h1:ECDRehsR9TYTKCAsRS8/wLeOk6UUqDydw47ln7wG41Q=
|
github.com/matterbridge/go-xmpp v0.0.0-20200328215643-8d36ff2c85d1/go.mod h1:ECDRehsR9TYTKCAsRS8/wLeOk6UUqDydw47ln7wG41Q=
|
||||||
github.com/matterbridge/gomatrix v0.0.0-20200209224845-c2104d7936a6 h1:Kl65VJv38HjYFnnwH+MP6Z8hcJT5UHuSpHVU5vW1HH0=
|
github.com/matterbridge/gomatrix v0.0.0-20200209224845-c2104d7936a6 h1:Kl65VJv38HjYFnnwH+MP6Z8hcJT5UHuSpHVU5vW1HH0=
|
||||||
github.com/matterbridge/gomatrix v0.0.0-20200209224845-c2104d7936a6/go.mod h1:+jWeaaUtXQbBRdKYWfjW6JDDYiI2XXE+3NnTjW5kg8g=
|
github.com/matterbridge/gomatrix v0.0.0-20200209224845-c2104d7936a6/go.mod h1:+jWeaaUtXQbBRdKYWfjW6JDDYiI2XXE+3NnTjW5kg8g=
|
||||||
github.com/matterbridge/gozulipbot v0.0.0-20190212232658-7aa251978a18 h1:fLhwXtWGtfTgZVxHG1lcKjv+re7dRwyyuYFNu69xdho=
|
github.com/matterbridge/gozulipbot v0.0.0-20190212232658-7aa251978a18 h1:fLhwXtWGtfTgZVxHG1lcKjv+re7dRwyyuYFNu69xdho=
|
||||||
|
|
|
@ -45,6 +45,9 @@ const (
|
||||||
// Default TLS configuration options
|
// Default TLS configuration options
|
||||||
var DefaultConfig tls.Config
|
var DefaultConfig tls.Config
|
||||||
|
|
||||||
|
// DebugWriter is the writer used to write debugging output to.
|
||||||
|
var DebugWriter io.Writer = os.Stderr
|
||||||
|
|
||||||
// Cookie is a unique XMPP session identifier
|
// Cookie is a unique XMPP session identifier
|
||||||
type Cookie uint64
|
type Cookie uint64
|
||||||
|
|
||||||
|
@ -191,21 +194,40 @@ type Options struct {
|
||||||
|
|
||||||
// Status message
|
// Status message
|
||||||
StatusMessage string
|
StatusMessage string
|
||||||
|
|
||||||
// Logger
|
|
||||||
Logger io.Writer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient establishes a new Client connection based on a set of Options.
|
// NewClient establishes a new Client connection based on a set of Options.
|
||||||
func (o Options) NewClient() (*Client, error) {
|
func (o Options) NewClient() (*Client, error) {
|
||||||
host := o.Host
|
host := o.Host
|
||||||
|
if strings.TrimSpace(host) == "" {
|
||||||
|
a := strings.SplitN(o.User, "@", 2)
|
||||||
|
if len(a) == 2 {
|
||||||
|
if _, addrs, err := net.LookupSRV("xmpp-client", "tcp", a[1]); err == nil {
|
||||||
|
if len(addrs) > 0 {
|
||||||
|
// default to first record
|
||||||
|
host = fmt.Sprintf("%s:%d", addrs[0].Target, addrs[0].Port)
|
||||||
|
defP := addrs[0].Priority
|
||||||
|
for _, adr := range addrs {
|
||||||
|
if adr.Priority < defP {
|
||||||
|
host = fmt.Sprintf("%s:%d", adr.Target, adr.Port)
|
||||||
|
defP = adr.Priority
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
host = a[1]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
host = a[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
c, err := connect(host, o.User, o.Password)
|
c, err := connect(host, o.User, o.Password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.LastIndex(o.Host, ":") > 0 {
|
if strings.LastIndex(host, ":") > 0 {
|
||||||
host = host[:strings.LastIndex(o.Host, ":")]
|
host = host[:strings.LastIndex(host, ":")]
|
||||||
}
|
}
|
||||||
|
|
||||||
client := new(Client)
|
client := new(Client)
|
||||||
|
@ -487,6 +509,8 @@ func (c *Client) startTLSIfRequired(f *streamFeatures, o *Options, domain string
|
||||||
case f.StartTLS == nil:
|
case f.StartTLS == nil:
|
||||||
// the server does not support STARTTLS
|
// the server does not support STARTTLS
|
||||||
return f, nil
|
return f, nil
|
||||||
|
case !o.StartTLS && f.StartTLS.Required == nil:
|
||||||
|
return f, nil
|
||||||
case f.StartTLS.Required != nil:
|
case f.StartTLS.Required != nil:
|
||||||
// the server requires STARTTLS.
|
// the server requires STARTTLS.
|
||||||
case !o.StartTLS:
|
case !o.StartTLS:
|
||||||
|
@ -527,7 +551,7 @@ func (c *Client) startTLSIfRequired(f *streamFeatures, o *Options, domain string
|
||||||
// will be returned.
|
// will be returned.
|
||||||
func (c *Client) startStream(o *Options, domain string) (*streamFeatures, error) {
|
func (c *Client) startStream(o *Options, domain string) (*streamFeatures, error) {
|
||||||
if o.Debug {
|
if o.Debug {
|
||||||
c.p = xml.NewDecoder(tee{c.conn, o.Logger})
|
c.p = xml.NewDecoder(tee{c.conn, DebugWriter})
|
||||||
} else {
|
} else {
|
||||||
c.p = xml.NewDecoder(c.conn)
|
c.p = xml.NewDecoder(c.conn)
|
||||||
}
|
}
|
||||||
|
@ -618,6 +642,11 @@ func (c *Client) Recv() (stanza interface{}, err error) {
|
||||||
}
|
}
|
||||||
switch v := val.(type) {
|
switch v := val.(type) {
|
||||||
case *clientMessage:
|
case *clientMessage:
|
||||||
|
if v.Event.XMLNS == XMPPNS_PUBSUB_EVENT {
|
||||||
|
// Handle Pubsub notifications
|
||||||
|
return pubsubClientToReturn(v.Event), nil
|
||||||
|
}
|
||||||
|
|
||||||
stamp, _ := time.Parse(
|
stamp, _ := time.Parse(
|
||||||
"2006-01-02T15:04:05Z",
|
"2006-01-02T15:04:05Z",
|
||||||
v.Delay.Stamp,
|
v.Delay.Stamp,
|
||||||
|
@ -644,25 +673,101 @@ func (c *Client) Recv() (stanza interface{}, err error) {
|
||||||
case *clientPresence:
|
case *clientPresence:
|
||||||
return Presence{v.From, v.To, v.Type, v.Show, v.Status}, nil
|
return Presence{v.From, v.To, v.Type, v.Show, v.Status}, nil
|
||||||
case *clientIQ:
|
case *clientIQ:
|
||||||
|
switch {
|
||||||
|
case v.Query.XMLName.Space == "urn:xmpp:ping":
|
||||||
// TODO check more strictly
|
// TODO check more strictly
|
||||||
if bytes.Equal(bytes.TrimSpace(v.Query), []byte(`<ping xmlns='urn:xmpp:ping'/>`)) || bytes.Equal(bytes.TrimSpace(v.Query), []byte(`<ping xmlns="urn:xmpp:ping"/>`)) {
|
|
||||||
err := c.SendResultPing(v.ID, v.From)
|
err := c.SendResultPing(v.ID, v.From)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Chat{}, err
|
return Chat{}, err
|
||||||
}
|
}
|
||||||
|
fallthrough
|
||||||
|
case v.Type == "error":
|
||||||
|
switch v.ID {
|
||||||
|
case "sub1":
|
||||||
|
// Pubsub subscription failed
|
||||||
|
var errs []clientPubsubError
|
||||||
|
err := xml.Unmarshal([]byte(v.Error.InnerXML), &errs)
|
||||||
|
if err != nil {
|
||||||
|
return PubsubSubscription{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var errsStr []string
|
||||||
|
for _, e := range errs {
|
||||||
|
errsStr = append(errsStr, e.XMLName.Local)
|
||||||
|
}
|
||||||
|
|
||||||
|
return PubsubSubscription{
|
||||||
|
Errors: errsStr,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
case v.Type == "result" && v.ID == "unsub1":
|
||||||
|
// Unsubscribing MAY contain a pubsub element. But it does
|
||||||
|
// not have to
|
||||||
|
return PubsubUnsubscription{
|
||||||
|
SubID: "",
|
||||||
|
JID: v.From,
|
||||||
|
Node: "",
|
||||||
|
Errors: nil,
|
||||||
|
}, nil
|
||||||
|
case v.Query.XMLName.Local == "pubsub":
|
||||||
|
switch v.ID {
|
||||||
|
case "sub1":
|
||||||
|
// Subscription or unsubscription was successful
|
||||||
|
var sub clientPubsubSubscription
|
||||||
|
err := xml.Unmarshal([]byte(v.Query.InnerXML), &sub)
|
||||||
|
if err != nil {
|
||||||
|
return PubsubSubscription{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return PubsubSubscription{
|
||||||
|
SubID: sub.SubID,
|
||||||
|
JID: sub.JID,
|
||||||
|
Node: sub.Node,
|
||||||
|
Errors: nil,
|
||||||
|
}, nil
|
||||||
|
case "unsub1":
|
||||||
|
var sub clientPubsubSubscription
|
||||||
|
err := xml.Unmarshal([]byte(v.Query.InnerXML), &sub)
|
||||||
|
if err != nil {
|
||||||
|
return PubsubUnsubscription{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return PubsubUnsubscription{
|
||||||
|
SubID: sub.SubID,
|
||||||
|
JID: v.From,
|
||||||
|
Node: sub.Node,
|
||||||
|
Errors: nil,
|
||||||
|
}, nil
|
||||||
|
case "items1", "items3":
|
||||||
|
var p clientPubsubItems
|
||||||
|
err := xml.Unmarshal([]byte(v.Query.InnerXML), &p)
|
||||||
|
if err != nil {
|
||||||
|
return PubsubItems{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return PubsubItems{
|
||||||
|
p.Node,
|
||||||
|
pubsubItemsToReturn(p.Items),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
case v.Query.XMLName.Local == "":
|
||||||
|
return IQ{ID: v.ID, From: v.From, To: v.To, Type: v.Type}, nil
|
||||||
|
default:
|
||||||
|
res, err := xml.Marshal(v.Query)
|
||||||
|
if err != nil {
|
||||||
|
return Chat{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return IQ{ID: v.ID, From: v.From, To: v.To, Type: v.Type,
|
||||||
|
Query: res}, nil
|
||||||
}
|
}
|
||||||
return IQ{ID: v.ID, From: v.From, To: v.To, Type: v.Type, Query: v.Query}, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send sends the message wrapped inside an XMPP message stanza body.
|
// Send sends the message wrapped inside an XMPP message stanza body.
|
||||||
func (c *Client) Send(chat Chat) (n int, err error) {
|
func (c *Client) Send(chat Chat) (n int, err error) {
|
||||||
var subtext = ``
|
var subtext, thdtext, oobtext, msgidtext, msgcorrecttext string
|
||||||
var thdtext = ``
|
|
||||||
var oobtext = ``
|
|
||||||
var msgidtext = ``
|
|
||||||
var msgcorrecttext = ``
|
|
||||||
if chat.Subject != `` {
|
if chat.Subject != `` {
|
||||||
subtext = `<subject>` + xmlEscape(chat.Subject) + `</subject>`
|
subtext = `<subject>` + xmlEscape(chat.Subject) + `</subject>`
|
||||||
}
|
}
|
||||||
|
@ -676,20 +781,25 @@ func (c *Client) Send(chat Chat) (n int, err error) {
|
||||||
}
|
}
|
||||||
oobtext += `</x>`
|
oobtext += `</x>`
|
||||||
}
|
}
|
||||||
|
|
||||||
if chat.ID != `` {
|
if chat.ID != `` {
|
||||||
msgidtext = `id='` + xmlEscape(chat.ID) + `'`
|
msgidtext = `id='` + xmlEscape(chat.ID) + `'`
|
||||||
|
} else {
|
||||||
|
msgidtext = `id='` + cnonce() + `'`
|
||||||
}
|
}
|
||||||
|
|
||||||
if chat.ReplaceID != `` {
|
if chat.ReplaceID != `` {
|
||||||
msgcorrecttext = `<replace id='` + xmlEscape(chat.ReplaceID) + `' xmlns='urn:xmpp:message-correct:0'/>`
|
msgcorrecttext = `<replace id='` + xmlEscape(chat.ReplaceID) + `' xmlns='urn:xmpp:message-correct:0'/>`
|
||||||
}
|
}
|
||||||
return fmt.Fprintf(c.conn, "<message to='%s' type='%s' " + msgidtext + " xml:lang='en'>" + subtext + "<body>%s</body>" + msgcorrecttext + oobtext + thdtext + "</message>",
|
|
||||||
xmlEscape(chat.Remote), xmlEscape(chat.Type), xmlEscape(chat.Text))
|
stanza := "<message to='%s' type='%s' " + msgidtext + " xml:lang='en'>" + subtext + "<body>%s</body>" + msgcorrecttext + oobtext + thdtext + "</message>"
|
||||||
|
|
||||||
|
return fmt.Fprintf(c.conn, stanza, xmlEscape(chat.Remote), xmlEscape(chat.Type), xmlEscape(chat.Text))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendOOB sends OOB data wrapped inside an XMPP message stanza, without actual body.
|
// SendOOB sends OOB data wrapped inside an XMPP message stanza, without actual body.
|
||||||
func (c *Client) SendOOB(chat Chat) (n int, err error) {
|
func (c *Client) SendOOB(chat Chat) (n int, err error) {
|
||||||
var thdtext = ``
|
var thdtext, oobtext string
|
||||||
var oobtext = ``
|
|
||||||
if chat.Thread != `` {
|
if chat.Thread != `` {
|
||||||
thdtext = `<thread>` + xmlEscape(chat.Thread) + `</thread>`
|
thdtext = `<thread>` + xmlEscape(chat.Thread) + `</thread>`
|
||||||
}
|
}
|
||||||
|
@ -700,8 +810,8 @@ func (c *Client) SendOOB(chat Chat) (n int, err error) {
|
||||||
}
|
}
|
||||||
oobtext += `</x>`
|
oobtext += `</x>`
|
||||||
}
|
}
|
||||||
return fmt.Fprintf(c.conn, "<message to='%s' type='%s' xml:lang='en'>" + oobtext + thdtext + "</message>",
|
return fmt.Fprintf(c.conn, "<message to='%s' type='%s' id='%s' xml:lang='en'>"+oobtext+thdtext+"</message>",
|
||||||
xmlEscape(chat.Remote), xmlEscape(chat.Type))
|
xmlEscape(chat.Remote), xmlEscape(chat.Type), cnonce())
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendOrg sends the original text without being wrapped in an XMPP message stanza.
|
// SendOrg sends the original text without being wrapped in an XMPP message stanza.
|
||||||
|
@ -818,6 +928,9 @@ type clientMessage struct {
|
||||||
Thread string `xml:"thread"`
|
Thread string `xml:"thread"`
|
||||||
ReplaceID clientMessageCorrect
|
ReplaceID clientMessageCorrect
|
||||||
|
|
||||||
|
// Pubsub
|
||||||
|
Event clientPubsubEvent `xml:"event"`
|
||||||
|
|
||||||
// Any hasn't matched element
|
// Any hasn't matched element
|
||||||
Other []XMLElement `xml:",any"`
|
Other []XMLElement `xml:",any"`
|
||||||
|
|
||||||
|
@ -882,13 +995,14 @@ type clientPresence struct {
|
||||||
Error *clientError
|
Error *clientError
|
||||||
}
|
}
|
||||||
|
|
||||||
type clientIQ struct { // info/query
|
type clientIQ struct {
|
||||||
|
// info/query
|
||||||
XMLName xml.Name `xml:"jabber:client iq"`
|
XMLName xml.Name `xml:"jabber:client iq"`
|
||||||
From string `xml:"from,attr"`
|
From string `xml:"from,attr"`
|
||||||
ID string `xml:"id,attr"`
|
ID string `xml:"id,attr"`
|
||||||
To string `xml:"to,attr"`
|
To string `xml:"to,attr"`
|
||||||
Type string `xml:"type,attr"` // error, get, result, set
|
Type string `xml:"type,attr"` // error, get, result, set
|
||||||
Query []byte `xml:",innerxml"`
|
Query XMLElement `xml:",any"`
|
||||||
Error clientError
|
Error clientError
|
||||||
Bind bindBind
|
Bind bindBind
|
||||||
}
|
}
|
||||||
|
@ -896,8 +1010,9 @@ type clientIQ struct { // info/query
|
||||||
type clientError struct {
|
type clientError struct {
|
||||||
XMLName xml.Name `xml:"jabber:client error"`
|
XMLName xml.Name `xml:"jabber:client error"`
|
||||||
Code string `xml:",attr"`
|
Code string `xml:",attr"`
|
||||||
Type string `xml:",attr"`
|
Type string `xml:"type,attr"`
|
||||||
Any xml.Name
|
Any xml.Name
|
||||||
|
InnerXML []byte `xml:",innerxml"`
|
||||||
Text string
|
Text string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
package xmpp
|
package xmpp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
"errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -47,33 +47,33 @@ func (c *Client) JoinMUC(jid, nick string, history_type, history int, history_da
|
||||||
}
|
}
|
||||||
switch history_type {
|
switch history_type {
|
||||||
case NoHistory:
|
case NoHistory:
|
||||||
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n" +
|
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n"+
|
||||||
"<x xmlns='%s' />\n" +
|
"<x xmlns='%s' />\n"+
|
||||||
"</presence>",
|
"</presence>",
|
||||||
xmlEscape(jid), xmlEscape(nick), nsMUC)
|
xmlEscape(jid), xmlEscape(nick), nsMUC)
|
||||||
case CharHistory:
|
case CharHistory:
|
||||||
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n" +
|
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n"+
|
||||||
"<x xmlns='%s'>\n" +
|
"<x xmlns='%s'>\n"+
|
||||||
"<history maxchars='%d'/></x>\n"+
|
"<history maxchars='%d'/></x>\n"+
|
||||||
"</presence>",
|
"</presence>",
|
||||||
xmlEscape(jid), xmlEscape(nick), nsMUC, history)
|
xmlEscape(jid), xmlEscape(nick), nsMUC, history)
|
||||||
case StanzaHistory:
|
case StanzaHistory:
|
||||||
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n" +
|
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n"+
|
||||||
"<x xmlns='%s'>\n" +
|
"<x xmlns='%s'>\n"+
|
||||||
"<history maxstanzas='%d'/></x>\n"+
|
"<history maxstanzas='%d'/></x>\n"+
|
||||||
"</presence>",
|
"</presence>",
|
||||||
xmlEscape(jid), xmlEscape(nick), nsMUC, history)
|
xmlEscape(jid), xmlEscape(nick), nsMUC, history)
|
||||||
case SecondsHistory:
|
case SecondsHistory:
|
||||||
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n" +
|
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n"+
|
||||||
"<x xmlns='%s'>\n" +
|
"<x xmlns='%s'>\n"+
|
||||||
"<history seconds='%d'/></x>\n"+
|
"<history seconds='%d'/></x>\n"+
|
||||||
"</presence>",
|
"</presence>",
|
||||||
xmlEscape(jid), xmlEscape(nick), nsMUC, history)
|
xmlEscape(jid), xmlEscape(nick), nsMUC, history)
|
||||||
case SinceHistory:
|
case SinceHistory:
|
||||||
if history_date != nil {
|
if history_date != nil {
|
||||||
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n" +
|
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n"+
|
||||||
"<x xmlns='%s'>\n" +
|
"<x xmlns='%s'>\n"+
|
||||||
"<history since='%s'/></x>\n" +
|
"<history since='%s'/></x>\n"+
|
||||||
"</presence>",
|
"</presence>",
|
||||||
xmlEscape(jid), xmlEscape(nick), nsMUC, history_date.Format(time.RFC3339))
|
xmlEscape(jid), xmlEscape(nick), nsMUC, history_date.Format(time.RFC3339))
|
||||||
}
|
}
|
||||||
|
@ -88,39 +88,39 @@ func (c *Client) JoinProtectedMUC(jid, nick string, password string, history_typ
|
||||||
}
|
}
|
||||||
switch history_type {
|
switch history_type {
|
||||||
case NoHistory:
|
case NoHistory:
|
||||||
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n" +
|
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n"+
|
||||||
"<x xmlns='%s'>\n" +
|
"<x xmlns='%s'>\n"+
|
||||||
"<password>%s</password>" +
|
"<password>%s</password>"+
|
||||||
"</x>\n" +
|
"</x>\n"+
|
||||||
"</presence>",
|
"</presence>",
|
||||||
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password))
|
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password))
|
||||||
case CharHistory:
|
case CharHistory:
|
||||||
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n" +
|
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n"+
|
||||||
"<x xmlns='%s'>\n" +
|
"<x xmlns='%s'>\n"+
|
||||||
"<password>%s</password>\n"+
|
"<password>%s</password>\n"+
|
||||||
"<history maxchars='%d'/></x>\n"+
|
"<history maxchars='%d'/></x>\n"+
|
||||||
"</presence>",
|
"</presence>",
|
||||||
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password), history)
|
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password), history)
|
||||||
case StanzaHistory:
|
case StanzaHistory:
|
||||||
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n" +
|
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n"+
|
||||||
"<x xmlns='%s'>\n" +
|
"<x xmlns='%s'>\n"+
|
||||||
"<password>%s</password>\n"+
|
"<password>%s</password>\n"+
|
||||||
"<history maxstanzas='%d'/></x>\n"+
|
"<history maxstanzas='%d'/></x>\n"+
|
||||||
"</presence>",
|
"</presence>",
|
||||||
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password), history)
|
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password), history)
|
||||||
case SecondsHistory:
|
case SecondsHistory:
|
||||||
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n" +
|
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n"+
|
||||||
"<x xmlns='%s'>\n" +
|
"<x xmlns='%s'>\n"+
|
||||||
"<password>%s</password>\n"+
|
"<password>%s</password>\n"+
|
||||||
"<history seconds='%d'/></x>\n"+
|
"<history seconds='%d'/></x>\n"+
|
||||||
"</presence>",
|
"</presence>",
|
||||||
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password), history)
|
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password), history)
|
||||||
case SinceHistory:
|
case SinceHistory:
|
||||||
if history_date != nil {
|
if history_date != nil {
|
||||||
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n" +
|
return fmt.Fprintf(c.conn, "<presence to='%s/%s'>\n"+
|
||||||
"<x xmlns='%s'>\n" +
|
"<x xmlns='%s'>\n"+
|
||||||
"<password>%s</password>\n"+
|
"<password>%s</password>\n"+
|
||||||
"<history since='%s'/></x>\n" +
|
"<history since='%s'/></x>\n"+
|
||||||
"</presence>",
|
"</presence>",
|
||||||
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password), history_date.Format(time.RFC3339))
|
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password), history_date.Format(time.RFC3339))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
package xmpp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
XMPPNS_PUBSUB = "http://jabber.org/protocol/pubsub"
|
||||||
|
XMPPNS_PUBSUB_EVENT = "http://jabber.org/protocol/pubsub#event"
|
||||||
|
)
|
||||||
|
|
||||||
|
type clientPubsubItem struct {
|
||||||
|
XMLName xml.Name `xml:"item"`
|
||||||
|
ID string `xml:"id,attr"`
|
||||||
|
Body []byte `xml:",innerxml"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type clientPubsubItems struct {
|
||||||
|
XMLName xml.Name `xml:"items"`
|
||||||
|
Node string `xml:"node,attr"`
|
||||||
|
Items []clientPubsubItem `xml:"item"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type clientPubsub struct {
|
||||||
|
XMLName xml.Name `xml:"pubsub"`
|
||||||
|
Items clientPubsubItems `xml:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type clientPubsubEvent struct {
|
||||||
|
XMLName xml.Name `xml:"event"`
|
||||||
|
XMLNS string `xml:"xmlns,attr"`
|
||||||
|
Items clientPubsubItems `xml:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type clientPubsubError struct {
|
||||||
|
XMLName xml.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
type clientPubsubSubscription struct {
|
||||||
|
XMLName xml.Name `xml:"subscription"`
|
||||||
|
Node string `xml:"node,attr"`
|
||||||
|
JID string `xml:"jid,attr"`
|
||||||
|
SubID string `xml:"subid,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PubsubEvent struct {
|
||||||
|
Node string
|
||||||
|
Items []PubsubItem
|
||||||
|
}
|
||||||
|
|
||||||
|
type PubsubSubscription struct {
|
||||||
|
SubID string
|
||||||
|
JID string
|
||||||
|
Node string
|
||||||
|
Errors []string
|
||||||
|
}
|
||||||
|
type PubsubUnsubscription PubsubSubscription
|
||||||
|
|
||||||
|
type PubsubItem struct {
|
||||||
|
ID string
|
||||||
|
InnerXML []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type PubsubItems struct {
|
||||||
|
Node string
|
||||||
|
Items []PubsubItem
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts []clientPubsubItem to []PubsubItem
|
||||||
|
func pubsubItemsToReturn(items []clientPubsubItem) []PubsubItem {
|
||||||
|
var tmp []PubsubItem
|
||||||
|
for _, i := range items {
|
||||||
|
tmp = append(tmp, PubsubItem{
|
||||||
|
ID: i.ID,
|
||||||
|
InnerXML: i.Body,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
func pubsubClientToReturn(event clientPubsubEvent) PubsubEvent {
|
||||||
|
return PubsubEvent{
|
||||||
|
Node: event.Items.Node,
|
||||||
|
Items: pubsubItemsToReturn(event.Items.Items),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func pubsubStanza(body string) string {
|
||||||
|
return fmt.Sprintf("<pubsub xmlns='%s'>%s</pubsub>",
|
||||||
|
XMPPNS_PUBSUB, body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pubsubSubscriptionStanza(node, jid string) string {
|
||||||
|
body := fmt.Sprintf("<subscribe node='%s' jid='%s'/>",
|
||||||
|
xmlEscape(node),
|
||||||
|
xmlEscape(jid))
|
||||||
|
return pubsubStanza(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pubsubUnsubscriptionStanza(node, jid string) string {
|
||||||
|
body := fmt.Sprintf("<unsubscribe node='%s' jid='%s'/>",
|
||||||
|
xmlEscape(node),
|
||||||
|
xmlEscape(jid))
|
||||||
|
return pubsubStanza(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) PubsubSubscribeNode(node, jid string) {
|
||||||
|
c.RawInformation(c.jid,
|
||||||
|
jid,
|
||||||
|
"sub1",
|
||||||
|
"set",
|
||||||
|
pubsubSubscriptionStanza(node, c.jid))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) PubsubUnsubscribeNode(node, jid string) {
|
||||||
|
c.RawInformation(c.jid,
|
||||||
|
jid,
|
||||||
|
"unsub1",
|
||||||
|
"set",
|
||||||
|
pubsubUnsubscriptionStanza(node, c.jid))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) PubsubRequestLastItems(node, jid string) {
|
||||||
|
body := fmt.Sprintf("<items node='%s'/>", node)
|
||||||
|
c.RawInformation(c.jid, jid, "items1", "get", pubsubStanza(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) PubsubRequestItem(node, jid, id string) {
|
||||||
|
body := fmt.Sprintf("<items node='%s'><item id='%s'/></items>", node, id)
|
||||||
|
c.RawInformation(c.jid, jid, "items3", "get", pubsubStanza(body))
|
||||||
|
}
|
|
@ -103,7 +103,7 @@ github.com/matterbridge/Rocket.Chat.Go.SDK/rest
|
||||||
github.com/matterbridge/discordgo
|
github.com/matterbridge/discordgo
|
||||||
# github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible
|
# github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible
|
||||||
github.com/matterbridge/emoji
|
github.com/matterbridge/emoji
|
||||||
# github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91
|
# github.com/matterbridge/go-xmpp v0.0.0-20200328215643-8d36ff2c85d1
|
||||||
github.com/matterbridge/go-xmpp
|
github.com/matterbridge/go-xmpp
|
||||||
# github.com/matterbridge/gomatrix v0.0.0-20200209224845-c2104d7936a6
|
# github.com/matterbridge/gomatrix v0.0.0-20200209224845-c2104d7936a6
|
||||||
github.com/matterbridge/gomatrix
|
github.com/matterbridge/gomatrix
|
||||||
|
|
Loading…
Reference in New Issue