package morningalarm import ( "context" "fmt" "math/rand" "net/http" "github.com/zmb3/spotify/v2" ) type headerTransport struct { baseTransport http.RoundTripper headers map[string]string } func (t *headerTransport) RoundTrip(req *http.Request) (*http.Response, error) { for key, value := range t.headers { req.Header.Set(key, value) } return t.baseTransport.RoundTrip(req) } func (ma *MorningAlarm) setupSpotifyWithProxy() { client := &http.Client{ Transport: &headerTransport{ baseTransport: http.DefaultTransport, headers: map[string]string{ "X-API-KEY": ma.config.OAuthProxyAPIKey, }, }, } ma.sp = spotify.New(client, spotify.WithBaseURL(ma.config.OAuthProxyURL)) } // playWakeUpMusic plays the playlist specified in the config at the specified device. // Returns true if the playback was started successfully. // Returns error if any error occurred. // Can still return an error even if the playback was started successfully. func (ma *MorningAlarm) playWakeUpMusic() (bool, error) { playContextURI := spotify.URI("spotify:playlist:" + ma.config.PlaylistID) devID, err := ma.getDeviceIDFromName(ma.config.DeviceName) if err != nil { return false, err } deviceID := spotify.ID(devID) playlist, err := ma.sp.GetPlaylistItems(context.Background(), spotify.ID(ma.config.PlaylistID)) if err != nil { return true, err } randomTrackIndex := rand.Intn(playlist.Total) err = ma.sp.PlayOpt(context.Background(), &spotify.PlayOptions{ PlaybackContext: &playContextURI, DeviceID: &deviceID, PlaybackOffset: &spotify.PlaybackOffset{Position: randomTrackIndex}, }) if err != nil { return true, err } err = ma.sp.ShuffleOpt(context.Background(), true, &spotify.PlayOptions{ DeviceID: &deviceID, }) return true, err } func (ma *MorningAlarm) getAvailableDevices() ([]Device, error) { devices, err := ma.sp.PlayerDevices(context.Background()) if err != nil { return nil, err } var availableDevices []Device for _, device := range devices { if !device.Restricted { availableDevices = append(availableDevices, Device{ ID: string(device.ID), Name: device.Name, }) } } return availableDevices, nil } func (ma *MorningAlarm) getDeviceIDFromName(name string) (string, error) { dev, err := ma.getAvailableDevices() if err != nil { return "", err } for _, device := range dev { if device.Name == name { return device.ID, nil } } return "", fmt.Errorf("device with name %s not found", name) }