Phase 3: OpenSubsonic core (response envelope, error codes 42-44, getOpenSubsonicExtensions) and apiKeyAuthentication extension with tokenInfo, web API key management

This commit is contained in:
2026-08-23 08:04:01 -05:00
parent 3b4883780b
commit e38d31d384
17 changed files with 763 additions and 37 deletions
+48
View File
@@ -0,0 +1,48 @@
package subsonic
import "sort"
func init() {
register("getOpenSubsonicExtensions", handleGetOpenSubsonicExtensions)
}
// extensionRegistry lists every OpenSubsonic extension VibeSonic
// actually implements and has tests for. Advertising an extension here
// is a promise the corresponding endpoint(s) really work — never add an
// entry just because a route exists. Each feature file registers its
// own entry via registerExtension() in its init().
var extensionRegistry = map[string][]int{}
func registerExtension(name string, versions ...int) {
if _, exists := extensionRegistry[name]; exists {
panic("subsonic: duplicate extension registration for " + name)
}
extensionRegistry[name] = versions
}
func supportedExtensions() []OpenSubsonicExtension {
names := make([]string, 0, len(extensionRegistry))
for n := range extensionRegistry {
names = append(names, n)
}
sort.Strings(names)
out := make([]OpenSubsonicExtension, 0, len(names))
for _, n := range names {
out = append(out, OpenSubsonicExtension{Name: n, Versions: extensionRegistry[n]})
}
return out
}
// hasExtension reports whether ext (any version) is advertised — used
// where a feature is fully optional and we want to fail closed if it
// were ever unregistered.
func hasExtension(name string) bool {
_, ok := extensionRegistry[name]
return ok
}
func handleGetOpenSubsonicExtensions(rc *Context) *apiError {
rc.Response = newResponse()
rc.Response.OpenSubsonicExtensions = supportedExtensions()
return nil
}