The schema defines the absence of state->open to represent the unknown state. Previously it was not possible to explicitly set this state via the HTTP endpoints. types.SpaceAPIState.Open is now an enum which is either unknown, closed, or open. Custom IsZero() and MarshalJSON() methods on the type ensure marshaling the value yields a boolean for open/closed and an empty byte slice for unknown (resulting in the field being absent from the final response). The handlers.StateOpenDELETE() function has been added to expose this behavior. Switching to encoding/json/v2 required raising the minimum Go version in go.mod to 1.27. Closes: CCCHH/spaceapid!37 Fixes: CCCHH/spaceapid#38
202 lines
6.1 KiB
Go
202 lines
6.1 KiB
Go
package types
|
|
|
|
import (
|
|
"encoding/json/v2"
|
|
)
|
|
|
|
const CurrentMessageVersion = "15"
|
|
|
|
// SpaceAPIResponse represents the contents of the SpaceAPI message
|
|
//
|
|
// Currently implemented version: 15
|
|
type SpaceAPIResponse struct {
|
|
APICompatibility []string `json:"api_compatibility"` // REQUIRED
|
|
Space string `json:"space"` // REQUIRED
|
|
Logo string `json:"logo"` // REQUIRED
|
|
URL string `json:"url"` // REQUIRED
|
|
|
|
// Minimum number of properties: 1
|
|
Location struct {
|
|
Address string `json:"address,omitzero"`
|
|
Lat float64 `json:"lat,omitzero"`
|
|
Lon float64 `json:"lon,omitzero"`
|
|
Timezone string `json:"timezone,omitzero"`
|
|
CountryCode string `json:"country_code,omitzero"`
|
|
Hint string `json:"hint,omitzero"`
|
|
// Minimum number of items: 1
|
|
Areas []SpaceAPILocationAreas `json:"areas,omitempty"`
|
|
} `json:"location,omitzero"`
|
|
|
|
SpaceFed struct {
|
|
SpaceNet bool `json:"spacenet,omitzero"`
|
|
SpaceSAML bool `json:"spacesaml,omitzero"`
|
|
} `json:"spacefed,omitzero"`
|
|
|
|
Cam []string `json:"cam,omitempty"`
|
|
|
|
State SpaceAPIState `json:"state,omitzero"`
|
|
|
|
Events []SpaceAPIEvents `json:"events,omitempty"`
|
|
|
|
Contact struct {
|
|
Phone string `json:"phone,omitzero"`
|
|
Sip string `json:"sip,omitzero"`
|
|
// keymasters
|
|
Keymasters []struct {
|
|
Name string `json:"name,omitzero"`
|
|
IRCNick string `json:"irc_nick,omitzero"`
|
|
Phone string `json:"phone,omitzero"`
|
|
Email string `json:"email,omitzero"`
|
|
Twitter string `json:"twitter,omitzero"`
|
|
Xmpp string `json:"xmpp,omitzero"`
|
|
Mastodon string `json:"mastodon,omitzero"`
|
|
Matrix string `json:"matrix,omitzero"`
|
|
} `json:"keymasters,omitempty"`
|
|
IRC string `json:"irc,omitzero"`
|
|
Twitter string `json:"twitter,omitzero"`
|
|
Mastodon string `json:"mastodon,omitzero"`
|
|
Facebook string `json:"facebook,omitzero"`
|
|
Identica string `json:"identica,omitzero"`
|
|
Foursquare string `json:"foursquare,omitzero"`
|
|
Email string `json:"email,omitzero"`
|
|
ML string `json:"ml,omitzero"`
|
|
XMPP string `json:"xmpp,omitzero"`
|
|
IssueMail string `json:"issue_mail,omitzero"`
|
|
Gopher string `json:"gopher,omitzero"`
|
|
Matrix string `json:"matrix,omitzero"`
|
|
Mumble string `json:"mumble,omitzero"`
|
|
} `json:"contact"`
|
|
|
|
Sensors map[string][]EnvironmentSensor `json:"sensors,omitempty"`
|
|
|
|
Feeds struct {
|
|
Blog struct {
|
|
Type string `json:"type,omitzero"`
|
|
URL string `json:"url"` // REQUIRED
|
|
} `json:"blog,omitzero"`
|
|
Wiki struct {
|
|
Type string `json:"type,omitzero"`
|
|
URL string `json:"url"` // REQUIRED
|
|
} `json:"wiki,omitzero"`
|
|
Calendar struct {
|
|
Type string `json:"type,omitzero"`
|
|
URL string `json:"url"` // REQUIRED
|
|
} `json:"calendar,omitzero"`
|
|
Flickr struct {
|
|
Type string `json:"type,omitzero"`
|
|
URL string `json:"url"` // REQUIRED
|
|
} `json:"flickr,omitzero"`
|
|
} `json:"feeds,omitzero"`
|
|
|
|
Projects []string `json:"projects,omitempty"`
|
|
|
|
Links []struct {
|
|
Name string `json:"name"` // REQUIRED
|
|
URL string `json:"url"` // REQUIRED
|
|
Description string `json:"description,omitzero"`
|
|
} `json:"links,omitempty"`
|
|
|
|
MembershipPlans []struct {
|
|
Name string `json:"name"` // REQUIRED
|
|
Value int64 `json:"value"` // REQUIRED
|
|
Currency string `json:"currency"` // REQUIRED
|
|
BillingInterval string `json:"billing_interval"` // REQUIRED
|
|
Description string `json:"description,omitzero"`
|
|
} `json:"membership_plans,omitempty"`
|
|
|
|
LinkedSpaces []struct {
|
|
Endpoint string `json:"endpoint,omitzero"`
|
|
Website string `json:"website,omitzero"`
|
|
} `json:"linked_spaces,omitempty"`
|
|
|
|
ExtCCC string `json:"ext_ccc,omitzero"`
|
|
}
|
|
|
|
type SpaceAPILocationAreas struct {
|
|
Name string `json:"name,omitzero"`
|
|
Description string `json:"description,omitzero"`
|
|
SquareMeters float64 `json:"square_meters"` // REQUIRED
|
|
}
|
|
|
|
type SpaceAPIStateOpen int
|
|
|
|
const (
|
|
SpaceAPIStateOpenIsUnknown = iota
|
|
SpaceAPIStateOpenIsClosed
|
|
SpaceAPIStateOpenIsOpen
|
|
)
|
|
|
|
func (state SpaceAPIStateOpen) MarshalJSON() ([]byte, error) {
|
|
switch state {
|
|
case SpaceAPIStateOpenIsClosed:
|
|
return json.Marshal(false)
|
|
case SpaceAPIStateOpenIsOpen:
|
|
return json.Marshal(true)
|
|
default:
|
|
return []byte{}, nil
|
|
}
|
|
}
|
|
|
|
func (state SpaceAPIStateOpen) IsZero() bool {
|
|
return state == SpaceAPIStateOpenIsUnknown
|
|
}
|
|
|
|
type SpaceAPIState struct {
|
|
Open SpaceAPIStateOpen `json:"open,omitzero"`
|
|
LastChange int64 `json:"lastchange,omitempty"`
|
|
TriggerPerson string `json:"trigger_person,omitempty"`
|
|
Message string `json:"message,omitempty"`
|
|
Icon struct {
|
|
Open string `json:"open,omitempty"` // REQUIRED
|
|
Closed string `json:"closed,omitempty"` // REQUIRED
|
|
} `json:"icon,omitzero"`
|
|
}
|
|
|
|
func (s *SpaceAPIState) FromPersistentSpaceState(ps PersistentState) {
|
|
if ps.State.IsUnknown {
|
|
s.Open = SpaceAPIStateOpenIsUnknown
|
|
} else {
|
|
if ps.State.Open {
|
|
s.Open = SpaceAPIStateOpenIsOpen
|
|
} else {
|
|
s.Open = SpaceAPIStateOpenIsClosed
|
|
}
|
|
}
|
|
s.LastChange = ps.State.LastChange
|
|
s.Message = ps.State.Message
|
|
}
|
|
|
|
type SpaceAPIEvents struct {
|
|
Name string `json:"name"` // REQUIRED
|
|
Type string `json:"type"` // REQUIRED
|
|
Timestamp int64 `json:"timestamp"` // REQUIRED
|
|
Extra string `json:"extra,omitzero"`
|
|
}
|
|
|
|
type EnvironmentSensor struct {
|
|
Value float64 `json:"value"`
|
|
Unit string `json:"unit"`
|
|
Location string `json:"location,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Description string `json:"description,omitempty"`
|
|
LastChange int64 `json:"lastchange,omitempty"`
|
|
}
|
|
|
|
type PersistentState struct {
|
|
State PersistentSpaceState `json:"state"`
|
|
Sensors map[string][]PersistentEnvironmentSensor `json:"sensors,omitempty"`
|
|
}
|
|
|
|
type PersistentSpaceState struct {
|
|
Open bool `json:"open"`
|
|
IsUnknown bool `json:"is_unknown"`
|
|
LastChange int64 `json:"lastchange"`
|
|
Message string `json:"message,omitempty"`
|
|
}
|
|
|
|
type PersistentEnvironmentSensor struct {
|
|
Value float64 `json:"value"`
|
|
Location string `json:"location,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
LastChange int64 `json:"lastchange"`
|
|
}
|