1package spec 2 3import ( 4 "fmt" 5 "time" 6 7 "senan.xyz/g/gonic/version" 8) 9 10var ( 11 apiVersion = "1.9.0" 12 xmlns = "http://subsonic.org/restapi" 13) 14 15type Response struct { 16 Status string `xml:"status,attr" json:"status"` 17 Version string `xml:"version,attr" json:"version"` 18 XMLNS string `xml:"xmlns,attr" json:"-"` 19 Type string `xml:"type,attr" json:"type"` 20 GonicVersion string `xml:"gonicVersion,attr" json:"gonicVersion"` 21 Error *Error `xml:"error" json:"error,omitempty"` 22 Albums *Albums `xml:"albumList" json:"albumList,omitempty"` 23 AlbumsTwo *Albums `xml:"albumList2" json:"albumList2,omitempty"` 24 Album *Album `xml:"album" json:"album,omitempty"` 25 Track *TrackChild `xml:"song" json:"song,omitempty"` 26 Indexes *Indexes `xml:"indexes" json:"indexes,omitempty"` 27 Artists *Artists `xml:"artists" json:"artists,omitempty"` 28 Artist *Artist `xml:"artist" json:"artist,omitempty"` 29 Directory *Directory `xml:"directory" json:"directory,omitempty"` 30 RandomTracks *RandomTracks `xml:"randomSongs" json:"randomSongs,omitempty"` 31 TracksByGenre *TracksByGenre `xml:"songsByGenre" json:"songsByGenre,omitempty"` 32 MusicFolders *MusicFolders `xml:"musicFolders" json:"musicFolders,omitempty"` 33 ScanStatus *ScanStatus `xml:"scanStatus" json:"scanStatus,omitempty"` 34 Licence *Licence `xml:"license" json:"license,omitempty"` 35 SearchResultTwo *SearchResultTwo `xml:"searchResult2" json:"searchResult2,omitempty"` 36 SearchResultThree *SearchResultThree `xml:"searchResult3" json:"searchResult3,omitempty"` 37 User *User `xml:"user" json:"user,omitempty"` 38 Playlists *Playlists `xml:"playlists" json:"playlists,omitempty"` 39 Playlist *Playlist `xml:"playlist" json:"playlist,omitempty"` 40 ArtistInfo *ArtistInfo `xml:"artistInfo" json:"artistInfo,omitempty"` 41 ArtistInfoTwo *ArtistInfo `xml:"artistInfo2" json:"artistInfo2,omitempty"` 42 Genres *Genres `xml:"genres" json:"genres,omitempty"` 43 PlayQueue *PlayQueue `xml:"playQueue" json:"playQueue,omitempty"` 44} 45 46func NewResponse() *Response { 47 return &Response{ 48 Status: "ok", 49 XMLNS: xmlns, 50 Version: apiVersion, 51 Type: version.NAME, 52 GonicVersion: version.VERSION, 53 } 54} 55 56// spec errors: 57// 0 a generic error 58// 10 required parameter is missing 59// 20 incompatible subsonic rest protocol version. client must upgrade 60// 30 incompatible subsonic rest protocol version. server must upgrade 61// 40 wrong username or password 62// 41 token authentication not supported for ldap users 63// 50 user is not authorized for the given operation 64// 60 the trial period for the subsonic server is over 65// 70 the requested data was not found 66type Error struct { 67 Code int `xml:"code,attr" json:"code"` 68 Message string `xml:"message,attr" json:"message"` 69} 70 71func NewError(code int, message string, a ...interface{}) *Response { 72 return &Response{ 73 Status: "failed", 74 XMLNS: xmlns, 75 Version: apiVersion, 76 Error: &Error{ 77 Code: code, 78 Message: fmt.Sprintf(message, a...), 79 }, 80 Type: version.NAME, 81 GonicVersion: version.VERSION, 82 } 83} 84 85type Albums struct { 86 List []*Album `xml:"album" json:"album"` 87} 88 89type Album struct { 90 // common 91 ID int `xml:"id,attr,omitempty" json:"id,string"` 92 CoverID int `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty,string"` 93 ArtistID int `xml:"artistId,attr,omitempty" json:"artistId,omitempty,string"` 94 Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"` 95 // browsing by folder (getAlbumList) 96 Title string `xml:"title,attr,omitempty" json:"title,omitempty"` 97 Album string `xml:"album,attr,omitempty" json:"album,omitempty"` 98 ParentID int `xml:"parent,attr,omitempty" json:"parent,omitempty,string"` 99 IsDir bool `xml:"isDir,attr,omitempty" json:"isDir,omitempty"` 100 // browsing by tags (getAlbumList2) 101 Name string `xml:"name,attr,omitempty" json:"name,omitempty"` 102 TrackCount int `xml:"songCount,attr" json:"songCount"` 103 Duration int `xml:"duration,attr" json:"duration"` 104 Created time.Time `xml:"created,attr,omitempty" json:"created,omitempty"` 105 Tracks []*TrackChild `xml:"song,omitempty" json:"song,omitempty"` 106} 107 108type RandomTracks struct { 109 List []*TrackChild `xml:"song" json:"song"` 110} 111 112type TracksByGenre struct { 113 List []*TrackChild `xml:"song" json:"song"` 114} 115 116type TrackChild struct { 117 Album string `xml:"album,attr,omitempty" json:"album,omitempty"` 118 AlbumID int `xml:"albumId,attr,omitempty" json:"albumId,omitempty,string"` 119 Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"` 120 ArtistID int `xml:"artistId,attr,omitempty" json:"artistId,omitempty,string"` 121 Bitrate int `xml:"bitRate,attr,omitempty" json:"bitRate,omitempty"` 122 ContentType string `xml:"contentType,attr,omitempty" json:"contentType,omitempty"` 123 CoverID int `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty,string"` 124 CreatedAt time.Time `xml:"created,attr,omitempty" json:"created,omitempty"` 125 Duration int `xml:"duration,attr,omitempty" json:"duration,omitempty"` 126 Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"` 127 ID int `xml:"id,attr,omitempty" json:"id,omitempty,string"` 128 IsDir bool `xml:"isDir,attr" json:"isDir"` 129 IsVideo bool `xml:"isVideo,attr" json:"isVideo"` 130 ParentID int `xml:"parent,attr,omitempty" json:"parent,omitempty,string"` 131 Path string `xml:"path,attr,omitempty" json:"path,omitempty"` 132 Size int `xml:"size,attr,omitempty" json:"size,omitempty"` 133 Suffix string `xml:"suffix,attr,omitempty" json:"suffix,omitempty"` 134 Title string `xml:"title,attr" json:"title"` 135 TrackNumber int `xml:"track,attr,omitempty" json:"track,omitempty"` 136 DiscNumber int `xml:"discNumber,attr,omitempty" json:"discNumber,omitempty"` 137 Type string `xml:"type,attr,omitempty" json:"type,omitempty"` 138} 139 140type Artists struct { 141 IgnoredArticles string `xml:"ignoredArticles,attr" json:"ignoredArticles"` 142 List []*Index `xml:"index" json:"index"` 143} 144 145type Artist struct { 146 ID int `xml:"id,attr,omitempty" json:"id,string"` 147 Name string `xml:"name,attr" json:"name"` 148 CoverID int `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty,string"` 149 AlbumCount int `xml:"albumCount,attr" json:"albumCount"` 150 Albums []*Album `xml:"album,omitempty" json:"album,omitempty"` 151} 152 153type Indexes struct { 154 LastModified int `xml:"lastModified,attr,omitempty" json:"lastModified"` 155 IgnoredArticles string `xml:"ignoredArticles,attr" json:"ignoredArticles"` 156 Index []*Index `xml:"index" json:"index"` 157} 158 159type Index struct { 160 Name string `xml:"name,attr,omitempty" json:"name"` 161 Artists []*Artist `xml:"artist" json:"artist"` 162} 163 164type Directory struct { 165 ID int `xml:"id,attr,omitempty" json:"id,string"` 166 ParentID int `xml:"parent,attr,omitempty" json:"parent,omitempty,string"` 167 Name string `xml:"name,attr,omitempty" json:"name"` 168 Starred string `xml:"starred,attr,omitempty" json:"starred,omitempty"` 169 Children []*TrackChild `xml:"child,omitempty" json:"child,omitempty"` 170} 171 172type MusicFolders struct { 173 List []*MusicFolder `xml:"musicFolder" json:"musicFolder"` 174} 175 176type MusicFolder struct { 177 ID int `xml:"id,attr,omitempty" json:"id,omitempty,string"` 178 Name string `xml:"name,attr,omitempty" json:"name,omitempty"` 179} 180 181type Licence struct { 182 Valid bool `xml:"valid,attr,omitempty" json:"valid,omitempty"` 183} 184 185type ScanStatus struct { 186 Scanning bool `xml:"scanning,attr" json:"scanning"` 187 Count int `xml:"count,attr,omitempty" json:"count,omitempty"` 188} 189 190type SearchResultTwo struct { 191 Artists []*Directory `xml:"artist,omitempty" json:"artist,omitempty"` 192 Albums []*TrackChild `xml:"album,omitempty" json:"album,omitempty"` 193 Tracks []*TrackChild `xml:"song,omitempty" json:"song,omitempty"` 194} 195 196type SearchResultThree struct { 197 Artists []*Artist `xml:"artist,omitempty" json:"artist,omitempty"` 198 Albums []*Album `xml:"album,omitempty" json:"album,omitempty"` 199 Tracks []*TrackChild `xml:"song,omitempty" json:"song,omitempty"` 200} 201 202type User struct { 203 Username string `xml:"username,attr" json:"username"` 204 ScrobblingEnabled bool `xml:"scrobblingEnabled,attr" json:"scrobblingEnabled"` 205 AdminRole bool `xml:"adminRole,attr" json:"adminRole"` 206 SettingsRole bool `xml:"settingsRole,attr" json:"settingsRole"` 207 DownloadRole bool `xml:"downloadRole,attr" json:"downloadRole"` 208 UploadRole bool `xml:"uploadRole,attr" json:"uploadRole"` 209 PlaylistRole bool `xml:"playlistRole,attr" json:"playlistRole"` 210 CoverArtRole bool `xml:"coverArtRole,attr" json:"coverArtRole"` 211 CommentRole bool `xml:"commentRole,attr" json:"commentRole"` 212 PodcastRole bool `xml:"podcastRole,attr" json:"podcastRole"` 213 StreamRole bool `xml:"streamRole,attr" json:"streamRole"` 214 JukeboxRole bool `xml:"jukeboxRole,attr" json:"jukeboxRole"` 215 ShareRole bool `xml:"shareRole,attr" json:"shareRole"` 216 VideoConversionRole bool `xml:"videoConversionRole,attr" json:"videoConversionRole"` 217 Folder []int `xml:"folder,attr" json:"folder"` 218} 219 220type Playlists struct { 221 List []*Playlist `xml:"playlist" json:"playlist"` 222} 223 224type Playlist struct { 225 ID int `xml:"id,attr" json:"id"` 226 Name string `xml:"name,attr" json:"name"` 227 Comment string `xml:"comment,attr" json:"comment"` 228 Owner string `xml:"owner,attr" json:"owner"` 229 SongCount int `xml:"songCount,attr" json:"songCount"` 230 Created time.Time `xml:"created,attr" json:"created"` 231 Duration string `xml:"duration,attr" json:"duration,omitempty"` 232 Public bool `xml:"public,attr" json:"public,omitempty"` 233 List []*TrackChild `xml:"entry" json:"entry"` 234} 235 236type SimilarArtist struct { 237 ID int `xml:"id,attr" json:"id,string"` 238 Name string `xml:"name,attr" json:"name"` 239 AlbumCount int `xml:"albumCount,attr,omitempty" json:"albumCount,omitempty"` 240} 241 242type ArtistInfo struct { 243 Biography string `xml:"biography" json:"biography"` 244 MusicBrainzID string `xml:"musicBrainzId" json:"musicBrainzId"` 245 LastFMURL string `xml:"lastFmUrl" json:"lastFmUrl"` 246 SmallImageURL string `xml:"smallImageUrl" json:"smallImageUrl"` 247 MediumImageURL string `xml:"mediumImageUrl" json:"mediumImageUrl"` 248 LargeImageURL string `xml:"largeImageUrl" json:"largeImageUrl"` 249 SimilarArtist []*SimilarArtist `xml:"similarArtist,omitempty" json:"similarArtist,omitempty"` 250} 251 252type Genres struct { 253 List []*Genre `xml:"genre" json:"genre"` 254} 255 256type Genre struct { 257 Name string `xml:",chardata" json:"value"` 258 SongCount int `xml:"songCount,attr,omitempty" json:"songCount,omitempty"` 259 AlbumCount int `xml:"albumCount,attr,omitempty" json:"albumCount,omitempty"` 260} 261 262type PlayQueue struct { 263 Current int `xml:"current,attr,omitempty" json:"current,omitempty"` 264 Position int `xml:"position,attr,omitempty" json:"position,omitempty"` 265 Username string `xml:"username,attr" json:"username"` 266 Changed time.Time `xml:"changed,attr" json:"changed"` 267 ChangedBy string `xml:"changedBy,attr" json:"changedBy"` 268 List []*TrackChild `xml:"entry,omitempty" json:"entry,omitempty"` 269} 270