Skip to content

Instantly share code, notes, and snippets.

@wichert
Created December 19, 2019 09:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wichert/dfd664d9077980c71b7e2064e5e7bdfe to your computer and use it in GitHub Desktop.
Save wichert/dfd664d9077980c71b7e2064e5e7bdfe to your computer and use it in GitHub Desktop.
go-xmpp roster
package stanza
import (
"encoding/xml"
"gosrc.io/xmpp/stanza"
)
const NSRoster = "jabber:iq:roster"
// SubscriptionNone indicates the user does not have a subscription to
// the contact's presence, and the contact does not have a subscription
// to the user's presence; this is the default value, so if the subscription
// attribute is not included then the state is to be understood as "none"
const SubscriptionNone = "none"
// SubscriptionTo indicates the user has a subscription to the contact's
// presence, but the contact does not have a subscription to the user's presence.
const SubscriptionTo = "to"
// SubscriptionFrom indicates the contact has a subscription to the user's
// presence, but the user does not have a subscription to the contact's presence
const SubscriptionFrom = "from"
// SubscriptionBoth indicates the user and the contact have subscriptions to each
// other's presence (also called a "mutual subscription")
const SubscriptionBoth = "both"
type Roster struct {
XMLName xml.Name `xml:"jabber:iq:roster query"`
stanza.IQPayload
Version string `xml:"ver,attr,omitempty"`
Items []RosterItem `xml:"item"`
}
func (p Roster) Namespace() string {
return p.XMLName.Space
}
func NewRoster(version string) Roster {
return Roster{Version: version}
}
type RosterItem struct {
XMLName xml.Name `xml:"jabber:iq:roster item"`
stanza.IQPayload
Jid string `xml:"jid,attr"`
Approved bool `xml:"approved,attr,omitempty"`
Ask string `xml:"ask,attr,omitempty"`
Name string `xml:"name,attr,omitempty"`
Subscription string `xml:"subscription,attr,omitempty"`
Groups []string `xml:"group"`
}
package stanza
import (
"encoding/xml"
"testing"
"gosrc.io/xmpp/stanza"
)
const RosterResponseSampleMessage = `
<?xml version="1.0"?>
<iq xmlns="jabber:client" from="3wraa9td8n9mpk5os712r6el0@crypho.com" to="3wraa9td8n9mpk5os712r6el0@crypho.com/rxsmv7l2k6k7zrmtbkjnjwwi1" id="b9455b04-972a-4cdb-9625-3938eca4e22f" type="result">
<query xmlns="jabber:iq:roster">
<item subscription="from" jid="admin@crypho.com"/>
<item subscription="both" jid="rdgccudqbgpgziaxpznvssba4@crypho.com">
<group>gcvk0u58ovovx9rq9hj1gdn81</group>
<group>1hdsvbytfj8tr2k7fjvuym5h2</group>
<group>t2csq2zurtqcf76ahhf06yrh5</group>
<group>4setk2o38fl02dldzfprp2dac</group>
<group>mveuf6m1e3iu45ndobmjq3tw9</group>
<group>0v577zwm7jqh8dovl7reor5pe</group>
<group>9yq6enwgmw1fmn72997hkaebc</group>
<group>nceaj8ie6zjmtfplnmcqpfdx3</group>
<group>fxz4xu0j85cs2h2rlibdsfya9</group>
<group>go1lpoitaj7o1gbbrmiz57zr2</group>
</item>
<item subscription="both" jid="9xszddnq4ffjxwyjvk51ckre7@crypho.com">
<group>jnku1isxx0vwede92jfcs40b6</group>
</item>
<item subscription="both" jid="75yjz67tmiaroj4jcbb401vi5@crypho.com">
<group>mveuf6m1e3iu45ndobmjq3tw9</group>
</item>
<item subscription="both" jid="eiqtjyjeuh27diaf4ols3y16e@crypho.com">
<group>mveuf6m1e3iu45ndobmjq3tw9</group>
</item>
<item subscription="both" jid="8v38kiiqhyv9icc49qmcbxacc@crypho.com">
<group>mveuf6m1e3iu45ndobmjq3tw9</group>
</item>
<item subscription="both" jid="9754b12ygv7ivfbqd8q4zanma@crypho.com">
<group>t2csq2zurtqcf76ahhf06yrh5</group>
<group>4setk2o38fl02dldzfprp2dac</group>
<group>zwwwm956gmu1vzh6cqoa10521</group>
<group>0v577zwm7jqh8dovl7reor5pe</group>
<group>9yq6enwgmw1fmn72997hkaebc</group>
<group>nceaj8ie6zjmtfplnmcqpfdx3</group>
<group>fxz4xu0j85cs2h2rlibdsfya9</group>
<group>go1lpoitaj7o1gbbrmiz57zr2</group>
</item>
<item subscription="both" jid="121ya66ctrdnn9k0p4we865e4@crypho.com">
<group>1hdsvbytfj8tr2k7fjvuym5h2</group>
<group>4setk2o38fl02dldzfprp2dac</group>
</item>
<item subscription="both" jid="k9dupta3yhipaadb5ov5g75xc@crypho.com">
<group>1hdsvbytfj8tr2k7fjvuym5h2</group>
<group>grj52p5ny624uz0zc2tldaea5</group>
<group>t2csq2zurtqcf76ahhf06yrh5</group>
<group>4setk2o38fl02dldzfprp2dac</group>
<group>mveuf6m1e3iu45ndobmjq3tw9</group>
<group>nceaj8ie6zjmtfplnmcqpfdx3</group>
<group>fxz4xu0j85cs2h2rlibdsfya9</group>
<group>go1lpoitaj7o1gbbrmiz57zr2</group>
</item>
<item subscription="both" jid="3cav8q69qx7m5f7tw7rsmlil3@crypho.com">
<group>yb272z2q1543h6t242vncul96</group>
<group>t2csq2zurtqcf76ahhf06yrh5</group>
<group>4setk2o38fl02dldzfprp2dac</group>
<group>nceaj8ie6zjmtfplnmcqpfdx3</group>
</item>
<item subscription="both" jid="9aynsym60zbu78jbdvpho7s68@crypho.com">
<group>mzaoy73i6ra5k502182zi1t97</group>
</item>
<item subscription="both" jid="xl8ceawrfu8zdneomw1h6h28d@crypho.com">
<group>0flucpm8i2jtrjhxw01uf1nd2</group>
<group>bm2bajg9ex4e1swiuju9i9nu5</group>
<group>rvjpanomi4ejpx42fpmffoac0</group>
<group>cswwkvcto0xu1m6bttb4p8xre</group>
</item>
</query>
</iq>
`
func TestUnmarshalRoster(t *testing.T) {
RegisterClientTypes()
iq := stanza.IQ{}
if err := xml.Unmarshal([]byte(RosterResponseSampleMessage), &iq); err != nil {
t.Fatalf("message error stanza unmarshall error: %v", err)
}
payload, ok := iq.Payload.(*Roster)
if !ok {
t.Fatalf("Roster extension was not found")
}
if len(payload.Items) != 12 {
t.Fatalf("Only %d (of 12) items decoded", len(payload.Items))
}
if payload.Items[0].Jid != "admin@crypho.com" {
t.Errorf("Incorrect ID for item 0: %v", payload.Items[0].Jid)
}
if len(payload.Items[0].Groups) != 0 {
t.Errorf("Incorrect number of groups for item 0: %d", len(payload.Items[0].Groups))
}
if len(payload.Items[1].Groups) != 10 {
t.Errorf("Incorrect number of groups for item 0: %d", len(payload.Items[1].Groups))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment