diff --git a/caldav/caldav.go b/caldav/caldav.go index 5ca8b24..ee33bcb 100644 --- a/caldav/caldav.go +++ b/caldav/caldav.go @@ -24,8 +24,15 @@ type CalendarCompRequest struct { Comps []CalendarCompRequest } +type CompFilter struct { + Name string + Start, End time.Time + Comps []CompFilter +} + type CalendarQuery struct { - Comp CalendarCompRequest + CompRequest CalendarCompRequest + CompFilter CompFilter } type CalendarObject struct { diff --git a/caldav/client.go b/caldav/client.go index f433b65..6c42556 100644 --- a/caldav/client.go +++ b/caldav/client.go @@ -141,6 +141,20 @@ func encodeCalendarReq(c *CalendarCompRequest) (*internal.Prop, error) { return internal.EncodeProp(&calDataReq, getLastModReq, getETagReq) } +func encodeCompFilter(filter *CompFilter) *compFilter { + encoded := compFilter{Name: filter.Name} + if !filter.Start.IsZero() || !filter.End.IsZero() { + encoded.TimeRange = &timeRange{ + Start: dateWithUTCTime(filter.Start), + End: dateWithUTCTime(filter.End), + } + } + for _, child := range filter.Comps { + encoded.CompFilters = append(encoded.CompFilters, *encodeCompFilter(&child)) + } + return &encoded +} + func decodeCalendarObjectList(ms *internal.Multistatus) ([]CalendarObject, error) { addrs := make([]CalendarObject, 0, len(ms.Responses)) for _, resp := range ms.Responses { @@ -176,12 +190,13 @@ func decodeCalendarObjectList(ms *internal.Multistatus) ([]CalendarObject, error } func (c *Client) QueryCalendar(calendar string, query *CalendarQuery) ([]CalendarObject, error) { - propReq, err := encodeCalendarReq(&query.Comp) + propReq, err := encodeCalendarReq(&query.CompRequest) if err != nil { return nil, err } calendarQuery := calendarQuery{Prop: propReq} + calendarQuery.Filter.CompFilter = *encodeCompFilter(&query.CompFilter) req, err := c.ic.NewXMLRequest("REPORT", calendar, &calendarQuery) if err != nil { return nil, err diff --git a/caldav/elements.go b/caldav/elements.go index 1fac8f7..b01a8d6 100644 --- a/caldav/elements.go +++ b/caldav/elements.go @@ -62,24 +62,25 @@ type calendarQuery struct { // https://tools.ietf.org/html/rfc4791#section-9.7 type filter struct { - XMLName xml.Name `xml:"urn:ietf:params:xml:ns:caldav filter"` - Comp compFilter `xml:"comp-filter"` + XMLName xml.Name `xml:"urn:ietf:params:xml:ns:caldav filter"` + CompFilter compFilter `xml:"comp-filter"` } // https://tools.ietf.org/html/rfc4791#section-9.7.1 type compFilter struct { - XMLName xml.Name `xml:"urn:ietf:params:xml:ns:caldav comp-filter"` - Name string `xml:"name,attr"` - IsNotDefined *struct{} `xml:"is-not-defined,omitempty"` - TimeRange *timeRange `xml:"time-range,omitempty"` - // TODO: prop-filter, comp-filter + XMLName xml.Name `xml:"urn:ietf:params:xml:ns:caldav comp-filter"` + Name string `xml:"name,attr"` + IsNotDefined *struct{} `xml:"is-not-defined,omitempty"` + TimeRange *timeRange `xml:"time-range,omitempty"` + CompFilters []compFilter `xml:"comp-filter,omitempty"` + // TODO: prop-filter } // https://tools.ietf.org/html/rfc4791#section-9.9 type timeRange struct { XMLName xml.Name `xml:"urn:ietf:params:xml:ns:caldav time-range"` - Start dateWithUTCTime `xml:"start,attr"` - End dateWithUTCTime `xml:"end,attr"` + Start dateWithUTCTime `xml:"start,attr,omitempty"` + End dateWithUTCTime `xml:"end,attr,omitempty"` } const dateWithUTCTimeLayout = "20060102T150405Z"