Add config for glangci-lint, lint, handle "wire" errors fo auth procedure
This commit is contained in:
66
.golangci.yml
Normal file
66
.golangci.yml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
run:
|
||||||
|
tests: false
|
||||||
|
skip-dirs:
|
||||||
|
- _example
|
||||||
|
modules-download-mode: readonly
|
||||||
|
allow-parallel-runners: true
|
||||||
|
go: '1.21'
|
||||||
|
output:
|
||||||
|
sort-results: true
|
||||||
|
linters-settings:
|
||||||
|
gosec:
|
||||||
|
excludes:
|
||||||
|
# Оно не используется для повышения безопасности или каких-то таких секъюрых вещей, оно используется для выборки
|
||||||
|
# произвольного элемента из массива, так что ИДИ НАХУЙ с этой проверкой и не еби мозги липовой безопасностью.
|
||||||
|
- G404 # Insecure random number source (rand)
|
||||||
|
linters:
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- errcheck
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
||||||
|
- asasalint
|
||||||
|
- asciicheck
|
||||||
|
- bodyclose
|
||||||
|
- containedctx
|
||||||
|
- contextcheck
|
||||||
|
- decorder
|
||||||
|
- durationcheck
|
||||||
|
- errchkjson
|
||||||
|
- errorlint
|
||||||
|
- exhaustive
|
||||||
|
- exportloopref
|
||||||
|
- gci
|
||||||
|
- ginkgolinter
|
||||||
|
- gocheckcompilerdirectives
|
||||||
|
- gocritic
|
||||||
|
- godot
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
- gosec
|
||||||
|
- gosmopolitan
|
||||||
|
- grouper
|
||||||
|
- importas
|
||||||
|
- ireturn
|
||||||
|
- makezero
|
||||||
|
- mirror
|
||||||
|
- nakedret
|
||||||
|
- nilerr
|
||||||
|
- nilnil
|
||||||
|
- nlreturn
|
||||||
|
- noctx
|
||||||
|
- nolintlint
|
||||||
|
- nonamedreturns
|
||||||
|
- predeclared
|
||||||
|
- promlinter
|
||||||
|
- reassign
|
||||||
|
- revive
|
||||||
|
- rowserrcheck
|
||||||
|
- stylecheck
|
||||||
|
- unconvert
|
||||||
|
- wastedassign
|
||||||
|
- whitespace
|
||||||
|
- wsl
|
||||||
10
README.md
10
README.md
@@ -3,12 +3,12 @@ go-xmpp
|
|||||||
|
|
||||||
go xmpp library.
|
go xmpp library.
|
||||||
|
|
||||||
[Original](https://github.com/rsc/rsc/blob/master/xmpp/xmpp.go) was done by [Russ Cox](https://github.com/rsc), then
|
[Original](https://github.com/rsc/rsc/blob/master/xmpp/xmpp.go) work done by [Russ Cox](https://github.com/rsc),
|
||||||
forked by [Yasuhiro Matsumoto](https://github.com/mattn).
|
then [Yasuhiro Matsumoto](https://github.com/mattn) fork it and continue to improve it.
|
||||||
|
|
||||||
Since both of them have amost zero interest in continuing develop of this lib, i decide to fork it.
|
Since both of them have almost zero interest to continue develop this lib, I decide to fork it.
|
||||||
|
|
||||||
Documentation can be found at [godoc project](https://godoc.org/github.com/eleksir/go-xmpp)
|
Documentation can be found at [godoc project](https://godoc.org/github.com/eleksir/go-xmpp)
|
||||||
|
|
||||||
This fork mainains my needs for xmpp protocol. Feel free to contribute via PR-s if you find it interesing too and feel
|
This fork maintains my needs for xmpp protocol. Feel free to contribute via PR-s if you find it interesting too and feel
|
||||||
that it needs more love than it already has.
|
that it needs more love than it already has. And of course fell free to for it if needed.
|
||||||
|
|||||||
5
go.mod
5
go.mod
@@ -2,4 +2,7 @@ module github.com/eleksir/go-xmpp
|
|||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require golang.org/x/crypto v0.10.0
|
require (
|
||||||
|
golang.org/x/crypto v0.10.0
|
||||||
|
golang.org/x/text v0.10.0
|
||||||
|
)
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -1,2 +1,4 @@
|
|||||||
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||||
|
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
|
||||||
|
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package xmpp
|
package xmpp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1" //nolint:gosec // go fuck yourself, gosec. You don't even fucking read rfc. So shout the fuck up.
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
XMPPNS_AVATAR_PEP_DATA = "urn:xmpp:avatar:data"
|
XMPPNS_AVATAR_PEP_DATA = "urn:xmpp:avatar:data" //nocritic:revive
|
||||||
XMPPNS_AVATAR_PEP_METADATA = "urn:xmpp:avatar:metadata"
|
XMPPNS_AVATAR_PEP_METADATA = "urn:xmpp:avatar:metadata" //nocritic:revive
|
||||||
)
|
)
|
||||||
|
|
||||||
type clientAvatarData struct {
|
type clientAvatarData struct {
|
||||||
@@ -52,8 +52,8 @@ type AvatarMetadata struct {
|
|||||||
|
|
||||||
func handleAvatarData(itemsBody []byte, from, id string) (AvatarData, error) {
|
func handleAvatarData(itemsBody []byte, from, id string) (AvatarData, error) {
|
||||||
var data clientAvatarData
|
var data clientAvatarData
|
||||||
err := xml.Unmarshal(itemsBody, &data)
|
|
||||||
if err != nil {
|
if err := xml.Unmarshal(itemsBody, &data); err != nil {
|
||||||
return AvatarData{}, err
|
return AvatarData{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,8 +64,9 @@ func handleAvatarData(itemsBody []byte, from, id string) (AvatarData, error) {
|
|||||||
return AvatarData{}, err
|
return AvatarData{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hash := sha1.Sum(dataRaw)
|
hash := sha1.Sum(dataRaw) //nolint:gosec // go fuck yourself, gosec. This exact mechanics described in standard.
|
||||||
hashStr := hex.EncodeToString(hash[:])
|
hashStr := hex.EncodeToString(hash[:])
|
||||||
|
|
||||||
if hashStr != id {
|
if hashStr != id {
|
||||||
return AvatarData{}, errors.New("SHA1 hashes do not match")
|
return AvatarData{}, errors.New("SHA1 hashes do not match")
|
||||||
}
|
}
|
||||||
@@ -77,9 +78,12 @@ func handleAvatarData(itemsBody []byte, from, id string) (AvatarData, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleAvatarMetadata(body []byte, from string) (AvatarMetadata, error) {
|
func handleAvatarMetadata(body []byte, from string) (AvatarMetadata, error) {
|
||||||
var meta clientAvatarMetadata
|
var (
|
||||||
err := xml.Unmarshal(body, &meta)
|
meta clientAvatarMetadata
|
||||||
if err != nil {
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if err = xml.Unmarshal(body, &meta); err != nil {
|
||||||
return AvatarMetadata{}, err
|
return AvatarMetadata{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,10 +95,10 @@ func handleAvatarMetadata(body []byte, from string) (AvatarMetadata, error) {
|
|||||||
ID: meta.Info.ID,
|
ID: meta.Info.ID,
|
||||||
Type: meta.Info.Type,
|
Type: meta.Info.Type,
|
||||||
URL: meta.Info.URL,
|
URL: meta.Info.URL,
|
||||||
}, nil
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// A wrapper for atoi which just returns -1 if an error occurs
|
// atoiw is a wrapper for atoi which just returns -1 if an error occurs.
|
||||||
func atoiw(str string) int {
|
func atoiw(str string) int {
|
||||||
i, err := strconv.Atoi(str)
|
i, err := strconv.Atoi(str)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -104,22 +108,22 @@ func atoiw(str string) int {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) AvatarSubscribeMetadata(jid string) {
|
func (c *Client) AvatarSubscribeMetadata(jid string) (string, error) {
|
||||||
c.PubsubSubscribeNode(XMPPNS_AVATAR_PEP_METADATA, jid)
|
return c.PubsubSubscribeNode(XMPPNS_AVATAR_PEP_METADATA, jid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) AvatarUnsubscribeMetadata(jid string) {
|
func (c *Client) AvatarUnsubscribeMetadata(jid string) (string, error) {
|
||||||
c.PubsubUnsubscribeNode(XMPPNS_AVATAR_PEP_METADATA, jid)
|
return c.PubsubUnsubscribeNode(XMPPNS_AVATAR_PEP_METADATA, jid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) AvatarRequestData(jid string) {
|
func (c *Client) AvatarRequestData(jid string) (string, error) {
|
||||||
c.PubsubRequestLastItems(XMPPNS_AVATAR_PEP_DATA, jid)
|
return c.PubsubRequestLastItems(XMPPNS_AVATAR_PEP_DATA, jid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) AvatarRequestDataByID(jid, id string) {
|
func (c *Client) AvatarRequestDataByID(jid, id string) (string, error) {
|
||||||
c.PubsubRequestItem(XMPPNS_AVATAR_PEP_DATA, jid, id)
|
return c.PubsubRequestItem(XMPPNS_AVATAR_PEP_DATA, jid, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) AvatarRequestMetadata(jid string) {
|
func (c *Client) AvatarRequestMetadata(jid string) (string, error) {
|
||||||
c.PubsubRequestLastItems(XMPPNS_AVATAR_PEP_METADATA, jid)
|
return c.PubsubRequestLastItems(XMPPNS_AVATAR_PEP_METADATA, jid)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
XMPPNS_DISCO_ITEMS = "http://jabber.org/protocol/disco#items"
|
XMPPNS_DISCO_ITEMS = "http://jabber.org/protocol/disco#items" //nocritic:revive
|
||||||
XMPPNS_DISCO_INFO = "http://jabber.org/protocol/disco#info"
|
XMPPNS_DISCO_INFO = "http://jabber.org/protocol/disco#info" //nocritic:revive
|
||||||
)
|
)
|
||||||
|
|
||||||
type clientDiscoFeature struct {
|
type clientDiscoFeature struct {
|
||||||
@@ -90,6 +90,7 @@ func clientIdentitiesToReturn(identities []clientDiscoIdentity) []DiscoIdentity
|
|||||||
|
|
||||||
func clientDiscoItemsToReturn(items []clientDiscoItem) []DiscoItem {
|
func clientDiscoItemsToReturn(items []clientDiscoItem) []DiscoItem {
|
||||||
var ret []DiscoItem
|
var ret []DiscoItem
|
||||||
|
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
ret = append(ret, DiscoItem{
|
ret = append(ret, DiscoItem{
|
||||||
Jid: item.Jid,
|
Jid: item.Jid,
|
||||||
|
|||||||
@@ -14,22 +14,25 @@ const IQTypeError = "error"
|
|||||||
func (c *Client) Discovery() (string, error) {
|
func (c *Client) Discovery() (string, error) {
|
||||||
// use getCookie for a pseudo random id.
|
// use getCookie for a pseudo random id.
|
||||||
reqID := strconv.FormatUint(uint64(getCookie()), 10)
|
reqID := strconv.FormatUint(uint64(getCookie()), 10)
|
||||||
|
|
||||||
return c.RawInformationQuery(c.jid, c.domain, reqID, IQTypeGet, XMPPNS_DISCO_ITEMS, "")
|
return c.RawInformationQuery(c.jid, c.domain, reqID, IQTypeGet, XMPPNS_DISCO_ITEMS, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiscoverNodeInfo discovers information about a node. Empty node queries info about server itself.
|
// DiscoverNodeInfo discovers information about a node. Empty node queries info about server itself.
|
||||||
func (c *Client) DiscoverNodeInfo(node string) (string, error) {
|
func (c *Client) DiscoverNodeInfo(node string) (string, error) {
|
||||||
query := fmt.Sprintf("<query xmlns='%s' node='%s'/>", XMPPNS_DISCO_INFO, node)
|
query := fmt.Sprintf("<query xmlns='%s' node='%s'/>", XMPPNS_DISCO_INFO, node)
|
||||||
|
|
||||||
return c.RawInformation(c.jid, c.domain, "info3", IQTypeGet, query)
|
return c.RawInformation(c.jid, c.domain, "info3", IQTypeGet, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiscoverInfo discovers information about given item from given jid.
|
// DiscoverInfo discovers information about given item from given jid.
|
||||||
func (c *Client) DiscoverInfo(from string, to string) (string, error) {
|
func (c *Client) DiscoverInfo(from string, to string) (string, error) {
|
||||||
query := fmt.Sprintf("<query xmlns='%s'/>", XMPPNS_DISCO_INFO)
|
query := fmt.Sprintf("<query xmlns='%s'/>", XMPPNS_DISCO_INFO)
|
||||||
|
|
||||||
return c.RawInformation(from, to, "info3", IQTypeGet, query)
|
return c.RawInformation(from, to, "info3", IQTypeGet, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiscoverServerItems discover items that the server exposes
|
// DiscoverServerItems discover items that the server exposes.
|
||||||
func (c *Client) DiscoverServerItems() (string, error) {
|
func (c *Client) DiscoverServerItems() (string, error) {
|
||||||
return c.DiscoverEntityItems(c.domain)
|
return c.DiscoverEntityItems(c.domain)
|
||||||
}
|
}
|
||||||
@@ -37,6 +40,7 @@ func (c *Client) DiscoverServerItems() (string, error) {
|
|||||||
// DiscoverEntityItems discovers items that an entity exposes.
|
// DiscoverEntityItems discovers items that an entity exposes.
|
||||||
func (c *Client) DiscoverEntityItems(jid string) (string, error) {
|
func (c *Client) DiscoverEntityItems(jid string) (string, error) {
|
||||||
query := fmt.Sprintf("<query xmlns='%s'/>", XMPPNS_DISCO_ITEMS)
|
query := fmt.Sprintf("<query xmlns='%s'/>", XMPPNS_DISCO_ITEMS)
|
||||||
|
|
||||||
return c.RawInformation(c.jid, jid, "info1", IQTypeGet, query)
|
return c.RawInformation(c.jid, jid, "info1", IQTypeGet, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +48,7 @@ func (c *Client) DiscoverEntityItems(jid string) (string, error) {
|
|||||||
func (c *Client) RawInformationQuery(from, to, id, iqType, requestNamespace, body string) (string, error) {
|
func (c *Client) RawInformationQuery(from, to, id, iqType, requestNamespace, body string) (string, error) {
|
||||||
const xmlIQ = "<iq from='%s' to='%s' id='%s' type='%s'><query xmlns='%s'>%s</query></iq>"
|
const xmlIQ = "<iq from='%s' to='%s' id='%s' type='%s'><query xmlns='%s'>%s</query></iq>"
|
||||||
_, err := fmt.Fprintf(StanzaWriter, xmlIQ, xmlEscape(from), xmlEscape(to), id, iqType, requestNamespace, body)
|
_, err := fmt.Fprintf(StanzaWriter, xmlIQ, xmlEscape(from), xmlEscape(to), id, iqType, requestNamespace, body)
|
||||||
|
|
||||||
return id, err
|
return id, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +56,7 @@ func (c *Client) RawInformationQuery(from, to, id, iqType, requestNamespace, bod
|
|||||||
func (c *Client) RawInformation(from, to, id, iqType, body string) (string, error) {
|
func (c *Client) RawInformation(from, to, id, iqType, body string) (string, error) {
|
||||||
const xmlIQ = "<iq from='%s' to='%s' id='%s' type='%s'>%s</iq>"
|
const xmlIQ = "<iq from='%s' to='%s' id='%s' type='%s'>%s</iq>"
|
||||||
_, err := fmt.Fprintf(StanzaWriter, xmlIQ, xmlEscape(from), xmlEscape(to), id, iqType, body)
|
_, err := fmt.Fprintf(StanzaWriter, xmlIQ, xmlEscape(from), xmlEscape(to), id, iqType, body)
|
||||||
|
|
||||||
return id, err
|
return id, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +70,7 @@ func (c *Client) IqVersionResponse(v IQ, name, version, os string) (string, erro
|
|||||||
version = "undefined"
|
version = "undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
query := "<query xmlns=\"jabber:iq:version\">" //nolint:wsl
|
query := "<query xmlns=\"jabber:iq:version\">"
|
||||||
query += fmt.Sprintf("<name>%s</name>", name)
|
query += fmt.Sprintf("<name>%s</name>", name)
|
||||||
query += fmt.Sprintf("<version>%s</version>", version)
|
query += fmt.Sprintf("<version>%s</version>", version)
|
||||||
|
|
||||||
@@ -100,9 +106,9 @@ func (c *Client) JabberIqLastResponse(v IQ, lastActivity int64) (string, error)
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UrnXmppTimeResponse implements response to query entity's current time (xep-0202).
|
// UrnXMPPTimeResponse implements response to query entity's current time (xep-0202).
|
||||||
// TimezoneOffset have format +HH:MM or -HH:MM
|
// TimezoneOffset have format +HH:MM or -HH:MM.
|
||||||
func (c *Client) UrnXmppTimeResponse(v IQ, timezoneOffset string) (string, error) {
|
func (c *Client) UrnXMPPTimeResponse(v IQ, timezoneOffset string) (string, error) {
|
||||||
query := fmt.Sprintf(
|
query := fmt.Sprintf(
|
||||||
"<time xmlns=\"urn:xmpp:time\"><tzo>%s</tzo><utc>%s</utc></time>",
|
"<time xmlns=\"urn:xmpp:time\"><tzo>%s</tzo><utc>%s</utc></time>",
|
||||||
timezoneOffset,
|
timezoneOffset,
|
||||||
|
|||||||
41
xmpp_muc.go
41
xmpp_muc.go
@@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// TODO(flo):
|
// TODO(flo):
|
||||||
// - support password protected MUC rooms
|
|
||||||
// - cleanup signatures of join/leave functions
|
// - cleanup signatures of join/leave functions
|
||||||
package xmpp
|
package xmpp
|
||||||
|
|
||||||
@@ -23,16 +22,18 @@ const (
|
|||||||
SinceHistory = 4
|
SinceHistory = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
// Send sends room topic wrapped inside an XMPP message stanza body.
|
// SendTopic sends room topic wrapped inside an XMPP message stanza body.
|
||||||
func (c *Client) SendTopic(chat Chat) (n int, err error) {
|
func (c *Client) SendTopic(chat Chat) (int, error) {
|
||||||
return fmt.Fprintf(StanzaWriter, "<message to='%s' type='%s' xml:lang='en'>"+"<subject>%s</subject></message>",
|
return fmt.Fprintf(StanzaWriter, "<message to='%s' type='%s' xml:lang='en'>"+"<subject>%s</subject></message>",
|
||||||
xmlEscape(chat.Remote), xmlEscape(chat.Type), xmlEscape(chat.Text))
|
xmlEscape(chat.Remote), xmlEscape(chat.Type), xmlEscape(chat.Text))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) JoinMUCNoHistory(jid, nick string) (n int, err error) {
|
// JoinMUCNoHistory joins room and instructs server that no history data required.
|
||||||
|
func (c *Client) JoinMUCNoHistory(jid, nick string) (int, error) {
|
||||||
if nick == "" {
|
if nick == "" {
|
||||||
nick = c.jid
|
nick = c.jid
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
|
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
|
||||||
"<x xmlns='%s'>"+
|
"<x xmlns='%s'>"+
|
||||||
"<history maxchars='0'/></x>\n"+
|
"<history maxchars='0'/></x>\n"+
|
||||||
@@ -40,12 +41,13 @@ func (c *Client) JoinMUCNoHistory(jid, nick string) (n int, err error) {
|
|||||||
xmlEscape(jid), xmlEscape(nick), nsMUC)
|
xmlEscape(jid), xmlEscape(nick), nsMUC)
|
||||||
}
|
}
|
||||||
|
|
||||||
// xep-0045 7.2
|
// JoinMUC joins room, xep-0045 7.2.
|
||||||
func (c *Client) JoinMUC(jid, nick string, history_type, history int, history_date *time.Time) (n int, err error) {
|
func (c *Client) JoinMUC(jid, nick string, historyType, history int, historyDate *time.Time) (int, error) {
|
||||||
if nick == "" {
|
if nick == "" {
|
||||||
nick = c.jid
|
nick = c.jid
|
||||||
}
|
}
|
||||||
switch history_type {
|
|
||||||
|
switch historyType {
|
||||||
case NoHistory:
|
case NoHistory:
|
||||||
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
|
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
|
||||||
"<x xmlns='%s' />\n"+
|
"<x xmlns='%s' />\n"+
|
||||||
@@ -70,23 +72,25 @@ func (c *Client) JoinMUC(jid, nick string, history_type, history int, history_da
|
|||||||
"</presence>",
|
"</presence>",
|
||||||
xmlEscape(jid), xmlEscape(nick), nsMUC, history)
|
xmlEscape(jid), xmlEscape(nick), nsMUC, history)
|
||||||
case SinceHistory:
|
case SinceHistory:
|
||||||
if history_date != nil {
|
if historyDate != nil {
|
||||||
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
|
return fmt.Fprintf(StanzaWriter, "<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, historyDate.Format(time.RFC3339))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0, errors.New("Unknown history option")
|
|
||||||
|
return 0, errors.New("unknown history option")
|
||||||
}
|
}
|
||||||
|
|
||||||
// xep-0045 7.2.6
|
// JoinProtectedMUC joins password protected room, xep-0045 7.2.6.
|
||||||
func (c *Client) JoinProtectedMUC(jid, nick string, password string, history_type, history int, history_date *time.Time) (n int, err error) {
|
func (c *Client) JoinProtectedMUC(jid, nick string, password string, historyType, history int, historyDate *time.Time) (int, error) {
|
||||||
if nick == "" {
|
if nick == "" {
|
||||||
nick = c.jid
|
nick = c.jid
|
||||||
}
|
}
|
||||||
switch history_type {
|
|
||||||
|
switch historyType {
|
||||||
case NoHistory:
|
case NoHistory:
|
||||||
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
|
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
|
||||||
"<x xmlns='%s'>\n"+
|
"<x xmlns='%s'>\n"+
|
||||||
@@ -116,20 +120,21 @@ func (c *Client) JoinProtectedMUC(jid, nick string, password string, history_typ
|
|||||||
"</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 historyDate != nil {
|
||||||
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
|
return fmt.Fprintf(StanzaWriter, "<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), historyDate.Format(time.RFC3339))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0, errors.New("Unknown history option")
|
|
||||||
|
return 0, errors.New("unknown history option")
|
||||||
}
|
}
|
||||||
|
|
||||||
// xep-0045 7.14
|
// LeaveMUC quits from room xep-0045 7.14.
|
||||||
func (c *Client) LeaveMUC(jid string) (n int, err error) {
|
func (c *Client) LeaveMUC(jid string) (int, error) {
|
||||||
return fmt.Fprintf(StanzaWriter, "<presence from='%s' to='%s' type='unavailable' />",
|
return fmt.Fprintf(StanzaWriter, "<presence from='%s' to='%s' type='unavailable' />",
|
||||||
c.jid, xmlEscape(jid))
|
c.jid, xmlEscape(jid))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,16 @@ func (c *Client) PingC2S(jid, server string) error {
|
|||||||
if jid == "" {
|
if jid == "" {
|
||||||
jid = c.jid
|
jid = c.jid
|
||||||
}
|
}
|
||||||
|
|
||||||
if server == "" {
|
if server == "" {
|
||||||
server = c.domain
|
server = c.domain
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := fmt.Fprintf(StanzaWriter, "<iq from='%s' to='%s' id='c2s1' type='get'>\n"+
|
_, err := fmt.Fprintf(StanzaWriter, "<iq from='%s' to='%s' id='c2s1' type='get'>\n"+
|
||||||
"<ping xmlns='urn:xmpp:ping'/>\n"+
|
"<ping xmlns='urn:xmpp:ping'/>\n"+
|
||||||
"</iq>",
|
"</iq>",
|
||||||
xmlEscape(jid), xmlEscape(server))
|
xmlEscape(jid), xmlEscape(server))
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,16 +26,18 @@ func (c *Client) PingS2S(fromServer, toServer string) error {
|
|||||||
"<ping xmlns='urn:xmpp:ping'/>\n"+
|
"<ping xmlns='urn:xmpp:ping'/>\n"+
|
||||||
"</iq>",
|
"</iq>",
|
||||||
xmlEscape(fromServer), xmlEscape(toServer))
|
xmlEscape(fromServer), xmlEscape(toServer))
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) SendResultPing(id, toServer string) error {
|
func (c *Client) SendResultPing(id, toServer string) error {
|
||||||
_, err := fmt.Fprintf(StanzaWriter, "<iq type='result' to='%s' id='%s'/>",
|
_, err := fmt.Fprintf(StanzaWriter, "<iq type='result' to='%s' id='%s'/>",
|
||||||
xmlEscape(toServer), xmlEscape(id))
|
xmlEscape(toServer), xmlEscape(id))
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// PingResponse responding to ping query according to xep-0199
|
// PingResponse responding to ping query according to xep-0199.
|
||||||
func (c *Client) PingResponse(v IQ) (string, error) {
|
func (c *Client) PingResponse(v IQ) (string, error) {
|
||||||
return c.RawInformation(
|
return c.RawInformation(
|
||||||
v.To,
|
v.To,
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
XMPPNS_PUBSUB = "http://jabber.org/protocol/pubsub"
|
XMPPNS_PUBSUB = "http://jabber.org/protocol/pubsub" //nolint:revive
|
||||||
XMPPNS_PUBSUB_EVENT = "http://jabber.org/protocol/pubsub#event"
|
XMPPNS_PUBSUB_EVENT = "http://jabber.org/protocol/pubsub#event" //nolint:revive
|
||||||
)
|
)
|
||||||
|
|
||||||
type clientPubsubItem struct {
|
type clientPubsubItem struct {
|
||||||
@@ -67,7 +67,7 @@ type PubsubItems struct {
|
|||||||
Items []PubsubItem
|
Items []PubsubItem
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts []clientPubsubItem to []PubsubItem
|
// Converts []clientPubsubItem to []PubsubItem.
|
||||||
func pubsubItemsToReturn(items []clientPubsubItem) []PubsubItem {
|
func pubsubItemsToReturn(items []clientPubsubItem) []PubsubItem {
|
||||||
var tmp []PubsubItem
|
var tmp []PubsubItem
|
||||||
for _, i := range items {
|
for _, i := range items {
|
||||||
@@ -96,6 +96,7 @@ func pubsubSubscriptionStanza(node, jid string) string {
|
|||||||
body := fmt.Sprintf("<subscribe node='%s' jid='%s'/>",
|
body := fmt.Sprintf("<subscribe node='%s' jid='%s'/>",
|
||||||
xmlEscape(node),
|
xmlEscape(node),
|
||||||
xmlEscape(jid))
|
xmlEscape(jid))
|
||||||
|
|
||||||
return pubsubStanza(body)
|
return pubsubStanza(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +104,7 @@ func pubsubUnsubscriptionStanza(node, jid string) string {
|
|||||||
body := fmt.Sprintf("<unsubscribe node='%s' jid='%s'/>",
|
body := fmt.Sprintf("<unsubscribe node='%s' jid='%s'/>",
|
||||||
xmlEscape(node),
|
xmlEscape(node),
|
||||||
xmlEscape(jid))
|
xmlEscape(jid))
|
||||||
|
|
||||||
return pubsubStanza(body)
|
return pubsubStanza(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,10 +126,12 @@ func (c *Client) PubsubUnsubscribeNode(node, jid string) (string, error) {
|
|||||||
|
|
||||||
func (c *Client) PubsubRequestLastItems(node, jid string) (string, error) {
|
func (c *Client) PubsubRequestLastItems(node, jid string) (string, error) {
|
||||||
body := fmt.Sprintf("<items node='%s'/>", node)
|
body := fmt.Sprintf("<items node='%s'/>", node)
|
||||||
|
|
||||||
return c.RawInformation(c.jid, jid, "items1", "get", pubsubStanza(body))
|
return c.RawInformation(c.jid, jid, "items1", "get", pubsubStanza(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) PubsubRequestItem(node, jid, id string) (string, error) {
|
func (c *Client) PubsubRequestItem(node, jid, id string) (string, error) {
|
||||||
body := fmt.Sprintf("<items node='%s'><item id='%s'/></items>", node, id)
|
body := fmt.Sprintf("<items node='%s'><item id='%s'/></items>", node, id)
|
||||||
|
|
||||||
return c.RawInformation(c.jid, jid, "items3", "get", pubsubStanza(body))
|
return c.RawInformation(c.jid, jid, "items3", "get", pubsubStanza(body))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,22 +4,30 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) ApproveSubscription(jid string) {
|
func (c *Client) ApproveSubscription(jid string) error {
|
||||||
fmt.Fprintf(StanzaWriter, "<presence to='%s' type='subscribed'/>",
|
_, err := fmt.Fprintf(StanzaWriter, "<presence to='%s' type='subscribed'/>",
|
||||||
xmlEscape(jid))
|
xmlEscape(jid))
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) RevokeSubscription(jid string) {
|
func (c *Client) RevokeSubscription(jid string) error {
|
||||||
fmt.Fprintf(StanzaWriter, "<presence to='%s' type='unsubscribed'/>",
|
_, err := fmt.Fprintf(StanzaWriter, "<presence to='%s' type='unsubscribed'/>",
|
||||||
xmlEscape(jid))
|
xmlEscape(jid))
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) RetrieveSubscription(jid string) {
|
func (c *Client) RetrieveSubscription(jid string) error {
|
||||||
fmt.Fprintf(c.conn, "<presence to='%s' type='unsubscribe'/>",
|
_, err := fmt.Fprintf(c.conn, "<presence to='%s' type='unsubscribe'/>",
|
||||||
xmlEscape(jid))
|
xmlEscape(jid))
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) RequestSubscription(jid string) {
|
func (c *Client) RequestSubscription(jid string) error {
|
||||||
fmt.Fprintf(StanzaWriter, "<presence to='%s' type='subscribe'/>",
|
_, err := fmt.Fprintf(StanzaWriter, "<presence to='%s' type='subscribe'/>",
|
||||||
xmlEscape(jid))
|
xmlEscape(jid))
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user