0

Initial commit

This commit is contained in:
eleksir
2023-09-17 12:18:09 +03:00
commit 843dd418b0
1514 changed files with 643531 additions and 0 deletions

30
vendor/github.com/eleksir/go-xmpp/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,30 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Copyright (c) 2012 Russ Cox <rsc@swtch.com>
Copyright (c) 2023 Yasuhiro Matsumoto <mattn.jp@gmail.com>
Copyright (c) 2023 Sergei Fedosoff <eleksir@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

14
vendor/github.com/eleksir/go-xmpp/README.md generated vendored Normal file
View File

@@ -0,0 +1,14 @@
go-xmpp
=======
go xmpp library.
[Original](https://github.com/rsc/rsc/blob/master/xmpp/xmpp.go) was done by [Russ Cox](https://github.com/rsc), then
forked by [Yasuhiro Matsumoto](https://github.com/mattn).
Since both of them have amost zero interest in continuing develop of this lib, i decide to fork it.
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
that it needs more love than it already has.

1455
vendor/github.com/eleksir/go-xmpp/xmpp.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

125
vendor/github.com/eleksir/go-xmpp/xmpp_avatar.go generated vendored Normal file
View File

@@ -0,0 +1,125 @@
package xmpp
import (
"crypto/sha1"
"encoding/base64"
"encoding/hex"
"encoding/xml"
"errors"
"strconv"
)
const (
XMPPNS_AVATAR_PEP_DATA = "urn:xmpp:avatar:data"
XMPPNS_AVATAR_PEP_METADATA = "urn:xmpp:avatar:metadata"
)
type clientAvatarData struct {
XMLName xml.Name `xml:"data"`
Data []byte `xml:",innerxml"`
}
type clientAvatarInfo struct {
XMLName xml.Name `xml:"info"`
Bytes string `xml:"bytes,attr"`
Width string `xml:"width,attr"`
Height string `xml:"height,attr"`
ID string `xml:"id,attr"`
Type string `xml:"type,attr"`
URL string `xml:"url,attr"`
}
type clientAvatarMetadata struct {
XMLName xml.Name `xml:"metadata"`
XMLNS string `xml:"xmlns,attr"`
Info clientAvatarInfo `xml:"info"`
}
type AvatarData struct {
Data []byte
From string
}
type AvatarMetadata struct {
From string
Bytes int
Width int
Height int
ID string
Type string
URL string
}
func handleAvatarData(itemsBody []byte, from, id string) (AvatarData, error) {
var data clientAvatarData
err := xml.Unmarshal(itemsBody, &data)
if err != nil {
return AvatarData{}, err
}
// Base64-decode the avatar data to check its SHA1 hash
dataRaw, err := base64.StdEncoding.DecodeString(
string(data.Data))
if err != nil {
return AvatarData{}, err
}
hash := sha1.Sum(dataRaw)
hashStr := hex.EncodeToString(hash[:])
if hashStr != id {
return AvatarData{}, errors.New("SHA1 hashes do not match")
}
return AvatarData{
Data: dataRaw,
From: from,
}, nil
}
func handleAvatarMetadata(body []byte, from string) (AvatarMetadata, error) {
var meta clientAvatarMetadata
err := xml.Unmarshal(body, &meta)
if err != nil {
return AvatarMetadata{}, err
}
return AvatarMetadata{
From: from,
Bytes: atoiw(meta.Info.Bytes),
Width: atoiw(meta.Info.Width),
Height: atoiw(meta.Info.Height),
ID: meta.Info.ID,
Type: meta.Info.Type,
URL: meta.Info.URL,
}, nil
}
// A wrapper for atoi which just returns -1 if an error occurs
func atoiw(str string) int {
i, err := strconv.Atoi(str)
if err != nil {
return -1
}
return i
}
func (c *Client) AvatarSubscribeMetadata(jid string) {
c.PubsubSubscribeNode(XMPPNS_AVATAR_PEP_METADATA, jid)
}
func (c *Client) AvatarUnsubscribeMetadata(jid string) {
c.PubsubUnsubscribeNode(XMPPNS_AVATAR_PEP_METADATA, jid)
}
func (c *Client) AvatarRequestData(jid string) {
c.PubsubRequestLastItems(XMPPNS_AVATAR_PEP_DATA, jid)
}
func (c *Client) AvatarRequestDataByID(jid, id string) {
c.PubsubRequestItem(XMPPNS_AVATAR_PEP_DATA, jid, id)
}
func (c *Client) AvatarRequestMetadata(jid string) {
c.PubsubRequestLastItems(XMPPNS_AVATAR_PEP_METADATA, jid)
}

102
vendor/github.com/eleksir/go-xmpp/xmpp_disco.go generated vendored Normal file
View File

@@ -0,0 +1,102 @@
package xmpp
import (
"encoding/xml"
)
const (
XMPPNS_DISCO_ITEMS = "http://jabber.org/protocol/disco#items"
XMPPNS_DISCO_INFO = "http://jabber.org/protocol/disco#info"
)
type clientDiscoFeature struct {
XMLName xml.Name `xml:"feature"`
Var string `xml:"var,attr"`
}
type clientDiscoIdentity struct {
XMLName xml.Name `xml:"identity"`
Category string `xml:"category,attr"`
Type string `xml:"type,attr"`
Name string `xml:"name,attr"`
}
type clientDiscoQuery struct {
XMLName xml.Name `xml:"query"`
Features []clientDiscoFeature `xml:"feature"`
Identities []clientDiscoIdentity `xml:"identity"`
}
type clientDiscoItem struct {
XMLName xml.Name `xml:"item"`
Jid string `xml:"jid,attr"`
Node string `xml:"node,attr"`
Name string `xml:"name,attr"`
}
type clientDiscoItemsQuery struct {
XMLName xml.Name `xml:"query"`
Items []clientDiscoItem `xml:"item"`
}
type DiscoIdentity struct {
Category string
Type string
Name string
}
type DiscoItem struct {
Jid string
Name string
Node string
}
type DiscoResult struct {
ID string
From string
To string
Features []string
Identities []DiscoIdentity
}
type DiscoItems struct {
Jid string
Items []DiscoItem
}
func clientFeaturesToReturn(features []clientDiscoFeature) []string {
var ret []string
for _, feature := range features {
ret = append(ret, feature.Var)
}
return ret
}
func clientIdentitiesToReturn(identities []clientDiscoIdentity) []DiscoIdentity {
var ret []DiscoIdentity
for _, id := range identities {
ret = append(ret, DiscoIdentity{
Category: id.Category,
Type: id.Type,
Name: id.Name,
})
}
return ret
}
func clientDiscoItemsToReturn(items []clientDiscoItem) []DiscoItem {
var ret []DiscoItem
for _, item := range items {
ret = append(ret, DiscoItem{
Jid: item.Jid,
Name: item.Name,
Node: item.Node,
})
}
return ret
}

57
vendor/github.com/eleksir/go-xmpp/xmpp_error.go generated vendored Normal file
View File

@@ -0,0 +1,57 @@
package xmpp
import (
"fmt"
)
// ErrorServiceUnavailable implements error response about feature that is not available. Currently implemented for
// xep-0030.
// QueryXmlns is about incoming xmlns attribute in query tag.
// Node is about incoming node attribute in query tag (looks like it used only in disco#commands).
//
// If queried feature is not here on purpose, standards suggest answer with this stanza.
func (c *Client) ErrorServiceUnavailable(v IQ, queryXmlns, node string) (string, error) {
query := fmt.Sprintf("<query xmlns=\"%s\" ", queryXmlns)
if node != "" {
query += fmt.Sprintf("node=\"%s\" />", node)
} else {
query += "/>"
}
query += "<error type=\"cancel\">"
query += "<service-unavailable xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\" />"
query += "</error>"
return c.RawInformation(
v.To,
v.From,
v.ID,
IQTypeError,
query,
)
}
// ErrorNotImplemented implements error response about feature that is not (yet?) implemented.
// Xmlns is about not implemented feature.
//
// If queried feature is not here because of it under development or for similar reasons, standards suggest answer with
// this stanza.
func (c *Client) ErrorNotImplemented(v IQ, xmlns, feature string) (string, error) {
query := "<error type=\"cancel\">"
query += "<feature-not-implemented xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\" />"
query += fmt.Sprintf(
"<unsupported xmlns=\"%s\" feature=\"%s\" />",
xmlns,
feature,
)
query += "</error>"
return c.RawInformation(
v.To,
v.From,
v.ID,
IQTypeError,
query,
)
}

View File

@@ -0,0 +1,119 @@
package xmpp
import (
"fmt"
"strconv"
"time"
)
const IQTypeGet = "get"
const IQTypeSet = "set"
const IQTypeResult = "result"
const IQTypeError = "error"
func (c *Client) Discovery() (string, error) {
// use getCookie for a pseudo random id.
reqID := strconv.FormatUint(uint64(getCookie()), 10)
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.
func (c *Client) DiscoverNodeInfo(node string) (string, error) {
query := fmt.Sprintf("<query xmlns='%s' node='%s'/>", XMPPNS_DISCO_INFO, node)
return c.RawInformation(c.jid, c.domain, "info3", IQTypeGet, query)
}
// DiscoverInfo discovers information about given item from given jid.
func (c *Client) DiscoverInfo(from string, to string) (string, error) {
query := fmt.Sprintf("<query xmlns='%s'/>", XMPPNS_DISCO_INFO)
return c.RawInformation(from, to, "info3", IQTypeGet, query)
}
// DiscoverServerItems discover items that the server exposes
func (c *Client) DiscoverServerItems() (string, error) {
return c.DiscoverEntityItems(c.domain)
}
// DiscoverEntityItems discovers items that an entity exposes.
func (c *Client) DiscoverEntityItems(jid string) (string, error) {
query := fmt.Sprintf("<query xmlns='%s'/>", XMPPNS_DISCO_ITEMS)
return c.RawInformation(c.jid, jid, "info1", IQTypeGet, query)
}
// RawInformationQuery sends an information query request to the server.
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>"
_, err := fmt.Fprintf(StanzaWriter, xmlIQ, xmlEscape(from), xmlEscape(to), id, iqType, requestNamespace, body)
return id, err
}
// RawInformation sends a IQ request with the payload body to the server.
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>"
_, err := fmt.Fprintf(StanzaWriter, xmlIQ, xmlEscape(from), xmlEscape(to), id, iqType, body)
return id, err
}
// IqVersionResponse responding with software version, according to xep-0092.
func (c *Client) IqVersionResponse(v IQ, name, version, os string) (string, error) {
if name == "" {
name = "go-xmpp"
}
if version == "" {
version = "undefined"
}
query := "<query xmlns=\"jabber:iq:version\">" //nolint:wsl
query += fmt.Sprintf("<name>%s</name>", name)
query += fmt.Sprintf("<version>%s</version>", version)
if os != "" {
query += fmt.Sprintf("<os>%s</os>", os)
}
query += "</query>"
return c.RawInformation(
v.To,
v.From,
v.ID,
IQTypeResult,
query,
)
}
// JabberIqLastResponse responding with relative time since last activity.
// Here lastActivity is unix time stamp when last activity took place since.
func (c *Client) JabberIqLastResponse(v IQ, lastActivity int64) (string, error) {
query := fmt.Sprintf(
"<query xmlns=\"jabber:iq:last\" seconds=\"%d\" />",
time.Now().Unix()-lastActivity,
)
return c.RawInformation(
v.To,
v.From,
v.ID,
IQTypeResult,
query,
)
}
// UrnXmppTimeResponse implements response to query entity's current time (xep-0202).
// TimezoneOffset have format +HH:MM or -HH:MM
func (c *Client) UrnXmppTimeResponse(v IQ, timezoneOffset string) (string, error) {
query := fmt.Sprintf(
"<time xmlns=\"urn:xmpp:time\"><tzo>%s</tzo><utc>%s</utc></time>",
timezoneOffset,
time.Now().UTC().Format(time.RFC3339),
)
return c.RawInformation(
v.To,
v.From,
v.ID,
IQTypeResult,
query,
)
}

135
vendor/github.com/eleksir/go-xmpp/xmpp_muc.go generated vendored Normal file
View File

@@ -0,0 +1,135 @@
// Copyright 2013 Flo Lauber <dev@qatfy.at>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// TODO(flo):
// - support password protected MUC rooms
// - cleanup signatures of join/leave functions
package xmpp
import (
"errors"
"fmt"
"time"
)
const (
nsMUC = "http://jabber.org/protocol/muc"
nsMUCUser = "http://jabber.org/protocol/muc#user"
NoHistory = 0
CharHistory = 1
StanzaHistory = 2
SecondsHistory = 3
SinceHistory = 4
)
// Send sends room topic wrapped inside an XMPP message stanza body.
func (c *Client) SendTopic(chat Chat) (n int, err error) {
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))
}
func (c *Client) JoinMUCNoHistory(jid, nick string) (n int, err error) {
if nick == "" {
nick = c.jid
}
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
"<x xmlns='%s'>"+
"<history maxchars='0'/></x>\n"+
"</presence>",
xmlEscape(jid), xmlEscape(nick), nsMUC)
}
// xep-0045 7.2
func (c *Client) JoinMUC(jid, nick string, history_type, history int, history_date *time.Time) (n int, err error) {
if nick == "" {
nick = c.jid
}
switch history_type {
case NoHistory:
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
"<x xmlns='%s' />\n"+
"</presence>",
xmlEscape(jid), xmlEscape(nick), nsMUC)
case CharHistory:
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
"<x xmlns='%s'>\n"+
"<history maxchars='%d'/></x>\n"+
"</presence>",
xmlEscape(jid), xmlEscape(nick), nsMUC, history)
case StanzaHistory:
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
"<x xmlns='%s'>\n"+
"<history maxstanzas='%d'/></x>\n"+
"</presence>",
xmlEscape(jid), xmlEscape(nick), nsMUC, history)
case SecondsHistory:
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
"<x xmlns='%s'>\n"+
"<history seconds='%d'/></x>\n"+
"</presence>",
xmlEscape(jid), xmlEscape(nick), nsMUC, history)
case SinceHistory:
if history_date != nil {
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
"<x xmlns='%s'>\n"+
"<history since='%s'/></x>\n"+
"</presence>",
xmlEscape(jid), xmlEscape(nick), nsMUC, history_date.Format(time.RFC3339))
}
}
return 0, errors.New("Unknown history option")
}
// 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) {
if nick == "" {
nick = c.jid
}
switch history_type {
case NoHistory:
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
"<x xmlns='%s'>\n"+
"<password>%s</password>"+
"</x>\n"+
"</presence>",
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password))
case CharHistory:
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
"<x xmlns='%s'>\n"+
"<password>%s</password>\n"+
"<history maxchars='%d'/></x>\n"+
"</presence>",
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password), history)
case StanzaHistory:
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
"<x xmlns='%s'>\n"+
"<password>%s</password>\n"+
"<history maxstanzas='%d'/></x>\n"+
"</presence>",
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password), history)
case SecondsHistory:
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
"<x xmlns='%s'>\n"+
"<password>%s</password>\n"+
"<history seconds='%d'/></x>\n"+
"</presence>",
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password), history)
case SinceHistory:
if history_date != nil {
return fmt.Fprintf(StanzaWriter, "<presence to='%s/%s'>\n"+
"<x xmlns='%s'>\n"+
"<password>%s</password>\n"+
"<history since='%s'/></x>\n"+
"</presence>",
xmlEscape(jid), xmlEscape(nick), nsMUC, xmlEscape(password), history_date.Format(time.RFC3339))
}
}
return 0, errors.New("Unknown history option")
}
// xep-0045 7.14
func (c *Client) LeaveMUC(jid string) (n int, err error) {
return fmt.Fprintf(StanzaWriter, "<presence from='%s' to='%s' type='unavailable' />",
c.jid, xmlEscape(jid))
}

44
vendor/github.com/eleksir/go-xmpp/xmpp_ping.go generated vendored Normal file
View File

@@ -0,0 +1,44 @@
package xmpp
import (
"fmt"
)
func (c *Client) PingC2S(jid, server string) error {
if jid == "" {
jid = c.jid
}
if server == "" {
server = c.domain
}
_, err := fmt.Fprintf(StanzaWriter, "<iq from='%s' to='%s' id='c2s1' type='get'>\n"+
"<ping xmlns='urn:xmpp:ping'/>\n"+
"</iq>",
xmlEscape(jid), xmlEscape(server))
return err
}
func (c *Client) PingS2S(fromServer, toServer string) error {
_, err := fmt.Fprintf(StanzaWriter, "<iq from='%s' to='%s' id='s2s1' type='get'>\n"+
"<ping xmlns='urn:xmpp:ping'/>\n"+
"</iq>",
xmlEscape(fromServer), xmlEscape(toServer))
return err
}
func (c *Client) SendResultPing(id, toServer string) error {
_, err := fmt.Fprintf(StanzaWriter, "<iq type='result' to='%s' id='%s'/>",
xmlEscape(toServer), xmlEscape(id))
return err
}
// PingResponse responding to ping query according to xep-0199
func (c *Client) PingResponse(v IQ) (string, error) {
return c.RawInformation(
v.To,
v.From,
v.ID,
IQTypeResult,
"",
)
}

133
vendor/github.com/eleksir/go-xmpp/xmpp_pubsub.go generated vendored Normal file
View File

@@ -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) (string, error) {
return c.RawInformation(c.jid,
jid,
"sub1",
"set",
pubsubSubscriptionStanza(node, c.jid))
}
func (c *Client) PubsubUnsubscribeNode(node, jid string) (string, error) {
return c.RawInformation(c.jid,
jid,
"unsub1",
"set",
pubsubUnsubscriptionStanza(node, c.jid))
}
func (c *Client) PubsubRequestLastItems(node, jid string) (string, error) {
body := fmt.Sprintf("<items node='%s'/>", node)
return c.RawInformation(c.jid, jid, "items1", "get", pubsubStanza(body))
}
func (c *Client) PubsubRequestItem(node, jid, id string) (string, error) {
body := fmt.Sprintf("<items node='%s'><item id='%s'/></items>", node, id)
return c.RawInformation(c.jid, jid, "items3", "get", pubsubStanza(body))
}

25
vendor/github.com/eleksir/go-xmpp/xmpp_subscription.go generated vendored Normal file
View File

@@ -0,0 +1,25 @@
package xmpp
import (
"fmt"
)
func (c *Client) ApproveSubscription(jid string) {
fmt.Fprintf(StanzaWriter, "<presence to='%s' type='subscribed'/>",
xmlEscape(jid))
}
func (c *Client) RevokeSubscription(jid string) {
fmt.Fprintf(StanzaWriter, "<presence to='%s' type='unsubscribed'/>",
xmlEscape(jid))
}
func (c *Client) RetrieveSubscription(jid string) {
fmt.Fprintf(c.conn, "<presence to='%s' type='unsubscribe'/>",
xmlEscape(jid))
}
func (c *Client) RequestSubscription(jid string) {
fmt.Fprintf(StanzaWriter, "<presence to='%s' type='subscribe'/>",
xmlEscape(jid))
}