mirror of
https://github.com/FluuxIO/go-xmpp.git
synced 2025-11-18 07:33:44 -08:00
Resync with Master
Support NullableInt on MUC presence history element
This commit is contained in:
@@ -2,6 +2,7 @@ package stanza
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -16,12 +17,130 @@ type MucPresence struct {
|
||||
History History `xml:"history,omitempty"`
|
||||
}
|
||||
|
||||
const timeLayout = "2006-01-02T15:04:05Z"
|
||||
|
||||
// History implements XEP-0045: Multi-User Chat - 19.1
|
||||
type History struct {
|
||||
MaxChars int `xml:"maxchars,attr,omitempty"`
|
||||
MaxStanzas int `xml:"maxstanzas,attr,omitempty"`
|
||||
Seconds int `xml:"seconds,attr,omitempty"`
|
||||
Since time.Time `xml:"since,attr,omitempty"`
|
||||
XMLName xml.Name
|
||||
MaxChars NullableInt `xml:"maxchars,attr,omitempty"`
|
||||
MaxStanzas NullableInt `xml:"maxstanzas,attr,omitempty"`
|
||||
Seconds NullableInt `xml:"seconds,attr,omitempty"`
|
||||
Since time.Time `xml:"since,attr,omitempty"`
|
||||
}
|
||||
|
||||
type NullableInt struct {
|
||||
Value int
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func NewNullableInt(val int) NullableInt {
|
||||
return NullableInt{val, true}
|
||||
}
|
||||
|
||||
func (n NullableInt) Get() (v int, ok bool) {
|
||||
return n.Value, n.isSet
|
||||
}
|
||||
|
||||
// UnmarshalXML implements custom parsing for history element
|
||||
func (h *History) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
h.XMLName = start.Name
|
||||
|
||||
// Extract attributes
|
||||
for _, attr := range start.Attr {
|
||||
switch attr.Name.Local {
|
||||
case "maxchars":
|
||||
v, err := strconv.Atoi(attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.MaxChars = NewNullableInt(v)
|
||||
case "maxstanzas":
|
||||
v, err := strconv.Atoi(attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.MaxStanzas = NewNullableInt(v)
|
||||
case "seconds":
|
||||
v, err := strconv.Atoi(attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.Seconds = NewNullableInt(v)
|
||||
case "since":
|
||||
t, err := time.Parse(timeLayout, attr.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.Since = t
|
||||
}
|
||||
}
|
||||
|
||||
// Consume remaining data until element end
|
||||
for {
|
||||
t, err := d.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tt := t.(type) {
|
||||
case xml.EndElement:
|
||||
if tt == start.End() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h History) MarshalXML(e *xml.Encoder, start xml.StartElement) (err error) {
|
||||
mc, isMcSet := h.MaxChars.Get()
|
||||
ms, isMsSet := h.MaxStanzas.Get()
|
||||
s, isSSet := h.Seconds.Get()
|
||||
|
||||
// We do not have any value, ignore history element
|
||||
if h.Since.IsZero() && !isMcSet && !isMsSet && !isSSet {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode start element and attributes
|
||||
start.Name = xml.Name{Local: "history"}
|
||||
|
||||
if isMcSet {
|
||||
attr := xml.Attr{
|
||||
Name: xml.Name{Local: "maxchars"},
|
||||
Value: strconv.Itoa(mc),
|
||||
}
|
||||
start.Attr = append(start.Attr, attr)
|
||||
}
|
||||
|
||||
if isMsSet {
|
||||
attr := xml.Attr{
|
||||
Name: xml.Name{Local: "maxstanzas"},
|
||||
Value: strconv.Itoa(ms),
|
||||
}
|
||||
start.Attr = append(start.Attr, attr)
|
||||
}
|
||||
|
||||
if isSSet {
|
||||
attr := xml.Attr{
|
||||
Name: xml.Name{Local: "seconds"},
|
||||
Value: strconv.Itoa(s),
|
||||
}
|
||||
start.Attr = append(start.Attr, attr)
|
||||
}
|
||||
|
||||
if !h.Since.IsZero() {
|
||||
attr := xml.Attr{
|
||||
Name: xml.Name{Local: "since"},
|
||||
Value: h.Since.Format(timeLayout),
|
||||
}
|
||||
start.Attr = append(start.Attr, attr)
|
||||
}
|
||||
if err := e.EncodeToken(start); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.EncodeToken(xml.EndElement{Name: start.Name})
|
||||
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
Reference in New Issue
Block a user