mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-24 14:47:23 +00:00
handlers_bmx.go had grown to ~426 lines covering registry + availability +
shared helpers + TuneIn (9 handlers) + Orion (2 handlers) + our own
custom-playback adapter. The test files were already split per service
(handlers_bmx_test.go, handlers_bmx_tunein_test.go,
handlers_bmx_report_test.go) — the production code now matches that
shape.
Pure move, no logic change:
- handlers_bmx.go → BMX registry + availability + shared
helpers (writeBMXUnauthorized,
bmxServicesJSON file-level vars)
- handlers_bmx_tunein.go → all TuneIn handlers (Playback,
PodcastInfo, PlaybackPodcast, Token,
Report, Navigate, Search, Favorite,
DeleteFavorite) plus tuneInStreamFormats
helper and parseTuneInNavigatePath
- handlers_bmx_orion.go → Orion (LOCAL_INTERNET_RADIO) Token +
Playback
- handlers_bmx_custom.go → our own /custom/v1/playback adapter
(not a Bose-official BMX service —
kept distinct from Orion for clarity)
Imports are tightened per file. No public API change; tests pass the
same as before this commit.
A future iteration may extract a common BMX-service interface once 3-4
services are fully implemented. Until then, file-per-service is the
shape — see memory project_bmx_service_interface.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
56 lines
1.5 KiB
Go
56 lines
1.5 KiB
Go
// Package handlers — AfterTouch's own custom-playback adapter (not a
|
|
// Bose-official BMX service). Reached via /custom/v1/playback/{encodedURL}
|
|
// by speakers that follow our LOCAL_INTERNET_RADIO preset locations.
|
|
//
|
|
// Split out of handlers_bmx.go on 2026-05-17; pure file move, no logic
|
|
// change.
|
|
package handlers
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/url"
|
|
|
|
"github.com/gesellix/bose-soundtouch/pkg/service/bmx"
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
// HandleCustomPlayback returns custom playback information for a given stream URL.
|
|
func (s *Server) HandleCustomPlayback(w http.ResponseWriter, r *http.Request) {
|
|
encodedURL := chi.URLParam(r, "encodedURL")
|
|
imageUrl := r.URL.Query().Get("imageUrl")
|
|
name := r.URL.Query().Get("name")
|
|
|
|
// Decode URL if it's base64 encoded
|
|
var streamUrl string
|
|
|
|
decoded, err := base64.URLEncoding.DecodeString(encodedURL)
|
|
if err != nil {
|
|
decoded, err = base64.StdEncoding.DecodeString(encodedURL)
|
|
}
|
|
|
|
if err == nil {
|
|
streamUrl = string(decoded)
|
|
} else {
|
|
// Try unescaping if it's not base64
|
|
streamUrl, err = url.PathUnescape(encodedURL)
|
|
if err != nil {
|
|
streamUrl = encodedURL
|
|
}
|
|
}
|
|
|
|
resp, err := bmx.BuildCustomStreamResponse(streamUrl, imageUrl, name)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
|
http.Error(w, "Failed to encode response", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|