-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpresence.go
217 lines (182 loc) · 5.43 KB
/
presence.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
// Copyright 2020 The jackal Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package stravaganza
import (
"errors"
"fmt"
"strconv"
)
const capabilitiesNamespace = "http://jabber.org/protocol/caps"
// PresenceName represents 'presence' stanza type name.
const PresenceName = "presence"
const (
// AvailableType represents an 'available' Presence type.
AvailableType = ""
// UnavailableType represents a 'unavailable' Presence type.
UnavailableType = "unavailable"
// SubscribeType represents a 'subscribe' Presence type.
SubscribeType = "subscribe"
// UnsubscribeType represents a 'unsubscribe' Presence type.
UnsubscribeType = "unsubscribe"
// SubscribedType represents a 'subscribed' Presence type.
SubscribedType = "subscribed"
// UnsubscribedType represents a 'unsubscribed' Presence type.
UnsubscribedType = "unsubscribed"
// ProbeType represents a 'probe' Presence type.
ProbeType = "probe"
)
// ShowState represents Presence show state.
type ShowState int
const (
// AvailableShowState represents 'available' Presence show state.
AvailableShowState ShowState = iota
// AwayShowState represents 'away' Presence show state.
AwayShowState
// ChatShowState represents 'chat' Presence show state.
ChatShowState
// DoNotDisturbShowState represents 'dnd' Presence show state.
DoNotDisturbShowState
// ExtendedAwaysShowState represents 'xa' Presence show state.
ExtendedAwaysShowState
)
// Capabilities represents presence entity capabilities
type Capabilities struct {
Node string
Hash string
Ver string
}
// Presence type represents a <presence> element.
type Presence struct {
stanza
showState ShowState
priority int8
}
// IsAvailable returns true if this is an 'available' type Presence.
func (p *Presence) IsAvailable() bool {
return p.Type() == AvailableType
}
// IsUnavailable returns true if this is an 'unavailable' type Presence.
func (p *Presence) IsUnavailable() bool {
return p.Type() == UnavailableType
}
// IsSubscribe returns true if this is a 'subscribe' type Presence.
func (p *Presence) IsSubscribe() bool {
return p.Type() == SubscribeType
}
// IsUnsubscribe returns true if this is an 'unsubscribe' type Presence.
func (p *Presence) IsUnsubscribe() bool {
return p.Type() == UnsubscribeType
}
// IsSubscribed returns true if this is a 'subscribed' type Presence.
func (p *Presence) IsSubscribed() bool {
return p.Type() == SubscribedType
}
// IsUnsubscribed returns true if this is an 'unsubscribed' type Presence.
func (p *Presence) IsUnsubscribed() bool {
return p.Type() == UnsubscribedType
}
// IsProbe returns true if this is an 'probe' type Presence.
func (p *Presence) IsProbe() bool {
return p.Type() == ProbeType
}
// Status returns presence stanza default status.
func (p *Presence) Status() string {
if st := p.Child("status"); st != nil {
return st.Text()
}
return ""
}
// ShowState returns presence stanza show state.
func (p *Presence) ShowState() ShowState {
return p.showState
}
// Priority returns presence stanza priority value.
func (p *Presence) Priority() int8 {
return p.priority
}
// Capabilities returns presence stanza capabilities element
func (p *Presence) Capabilities() *Capabilities {
c := p.ChildNamespace("c", capabilitiesNamespace)
if c == nil {
return nil
}
return &Capabilities{
Node: c.Attribute("node"),
Hash: c.Attribute("hash"),
Ver: c.Attribute("ver"),
}
}
func (p *Presence) validateStatus() error {
sts := p.Children("status")
for _, st := range sts {
switch st.AttributeCount() {
case 0:
break
case 1:
attrs := st.AllAttributes()
if attrs[0].Label == "xml:lang" {
break
}
fallthrough
default:
return errors.New("stravaganza: presence <status/> element MUST NOT possess any attributes, with the exception of the 'xml:lang' attribute")
}
}
return nil
}
func (p *Presence) setShow() error {
shs := p.Children("show")
switch len(shs) {
case 0:
p.showState = AvailableShowState
case 1:
if shs[0].AttributeCount() > 0 {
return errors.New("stravaganza: presence <show/> element MUST NOT possess any attributes")
}
switch shs[0].Text() {
case "away":
p.showState = AwayShowState
case "chat":
p.showState = ChatShowState
case "dnd":
p.showState = DoNotDisturbShowState
case "xa":
p.showState = ExtendedAwaysShowState
default:
return fmt.Errorf("stravaganza: invalid presence show state: %s", shs[0].Text())
}
default:
return errors.New("stravaganza: presence stanza MUST NOT contain more than one <show/> element")
}
return nil
}
func (p *Presence) setPriority() error {
ps := p.Children("priority")
switch len(ps) {
case 0:
break
case 1:
pr, err := strconv.Atoi(ps[0].Text())
if err != nil {
return err
}
if pr < -128 || pr > 127 {
return errors.New("stravaganza: presence priority value MUST be an integer between -128 and +127")
}
p.priority = int8(pr)
default:
return errors.New("stravaganza: a presence stanza MUST NOT contain more than one <priority/> element")
}
return nil
}