Phase 2: Subsonic REST API framework (auth, response formatting, error handling, routing) plus user permission model

This commit is contained in:
2026-08-22 23:58:54 -05:00
parent f81c8704a5
commit b5e2bf01e2
26 changed files with 1772 additions and 75 deletions
+96
View File
@@ -0,0 +1,96 @@
package subsonic
// --- Jukebox ---
type JukeboxStatus struct {
CurrentIndex int `xml:"currentIndex,attr" json:"currentIndex"`
Playing bool `xml:"playing,attr" json:"playing"`
Gain float64 `xml:"gain,attr" json:"gain"`
Position int `xml:"position,attr,omitempty" json:"position,omitempty"`
}
type JukeboxPlaylist struct {
JukeboxStatus
Entry []Child `xml:"entry,omitempty" json:"entry,omitempty"`
}
// --- Internet radio ---
type InternetRadioStations struct {
InternetRadioStation []InternetRadioStation `xml:"internetRadioStation,omitempty" json:"internetRadioStation,omitempty"`
}
type InternetRadioStation struct {
ID string `xml:"id,attr" json:"id"`
Name string `xml:"name,attr" json:"name"`
StreamURL string `xml:"streamUrl,attr" json:"streamUrl"`
HomepageURL string `xml:"homepageUrl,attr,omitempty" json:"homepageUrl,omitempty"`
}
// --- Chat ---
type ChatMessages struct {
ChatMessage []ChatMessage `xml:"chatMessage,omitempty" json:"chatMessage,omitempty"`
}
type ChatMessage struct {
Username string `xml:"username,attr" json:"username"`
Time int64 `xml:"time,attr" json:"time"` // millis since epoch
Message string `xml:"message,attr" json:"message"`
}
// --- Scan status ---
type ScanStatus struct {
Scanning bool `xml:"scanning,attr" json:"scanning"`
Count int64 `xml:"count,attr,omitempty" json:"count,omitempty"`
}
// --- Shares ---
type Shares struct {
Share []Share `xml:"share,omitempty" json:"share,omitempty"`
}
type Share struct {
ID string `xml:"id,attr" json:"id"`
URL string `xml:"url,attr" json:"url"`
Description string `xml:"description,attr,omitempty" json:"description,omitempty"`
Username string `xml:"username,attr" json:"username"`
Created string `xml:"created,attr" json:"created"`
Expires string `xml:"expires,attr,omitempty" json:"expires,omitempty"`
LastVisited string `xml:"lastVisited,attr,omitempty" json:"lastVisited,omitempty"`
VisitCount int64 `xml:"visitCount,attr" json:"visitCount"`
Entry []Child `xml:"entry,omitempty" json:"entry,omitempty"`
}
// --- Podcasts ---
type Podcasts struct {
Channel []PodcastChannel `xml:"channel,omitempty" json:"channel,omitempty"`
}
type NewestPodcasts struct {
Episode []PodcastEpisode `xml:"episode,omitempty" json:"episode,omitempty"`
}
type PodcastChannel struct {
ID string `xml:"id,attr" json:"id"`
URL string `xml:"url,attr" json:"url"`
Title string `xml:"title,attr,omitempty" json:"title,omitempty"`
Description string `xml:"description,attr,omitempty" json:"description,omitempty"`
CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"`
OriginalImageURL string `xml:"originalImageUrl,attr,omitempty" json:"originalImageUrl,omitempty"`
Status string `xml:"status,attr" json:"status"`
ErrorMessage string `xml:"errorMessage,attr,omitempty" json:"errorMessage,omitempty"`
Episode []PodcastEpisode `xml:"episode,omitempty" json:"episode,omitempty"`
}
type PodcastEpisode struct {
Child
StreamID string `xml:"streamId,attr,omitempty" json:"streamId,omitempty"`
ChannelID string `xml:"channelId,attr" json:"channelId"`
Description string `xml:"description,attr,omitempty" json:"description,omitempty"`
Status string `xml:"status,attr" json:"status"`
PublishDate string `xml:"publishDate,attr,omitempty" json:"publishDate,omitempty"`
}