Merge pull request 'fix issues when starting radio/playing track after device has gone inactive' (#7) from develop into main
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful

Reviewed-on: https://gitea.asdf.cafe/abs3nt/gospt/pulls/7
This commit is contained in:
abs3nt 2023-01-23 19:37:29 -08:00
commit 6ee12258d4
2 changed files with 144 additions and 25 deletions

View File

@ -66,11 +66,13 @@ func Play(ctx *gctx.Context, client *spotify.Client) error {
err := client.Play(ctx) err := client.Play(ctx)
if err != nil { if err != nil {
if isNoActiveError(err) { if isNoActiveError(err) {
err := activateDevice(ctx, client) deviceID, err := activateDevice(ctx, client)
if err != nil { if err != nil {
return err return err
} }
err = client.Play(ctx) err = client.PlayOpt(ctx, &spotify.PlayOptions{
DeviceID: &deviceID,
})
if err != nil { if err != nil {
return err return err
} }
@ -143,15 +145,19 @@ func PlayUrl(ctx *gctx.Context, client *spotify.Client, args []string) error {
err = client.QueueSong(ctx, spotify.ID(track_id)) err = client.QueueSong(ctx, spotify.ID(track_id))
if err != nil { if err != nil {
if isNoActiveError(err) { if isNoActiveError(err) {
err := activateDevice(ctx, client) deviceID, err := activateDevice(ctx, client)
if err != nil { if err != nil {
return err return err
} }
err = client.QueueSong(ctx, spotify.ID(track_id)) err = client.QueueSongOpt(ctx, spotify.ID(track_id), &spotify.PlayOptions{
DeviceID: &deviceID,
})
if err != nil { if err != nil {
return err return err
} }
err = client.Next(ctx) err = client.NextOpt(ctx, &spotify.PlayOptions{
DeviceID: &deviceID,
})
if err != nil { if err != nil {
return err return err
} }
@ -171,11 +177,13 @@ func QueueSong(ctx *gctx.Context, client *spotify.Client, id spotify.ID) error {
err := client.QueueSong(ctx, id) err := client.QueueSong(ctx, id)
if err != nil { if err != nil {
if isNoActiveError(err) { if isNoActiveError(err) {
err := activateDevice(ctx, client) deviceID, err := activateDevice(ctx, client)
if err != nil { if err != nil {
return err return err
} }
err = client.QueueSong(ctx, id) err = client.QueueSongOpt(ctx, id, &spotify.PlayOptions{
DeviceID: &deviceID,
})
if err != nil { if err != nil {
return err return err
} }
@ -194,14 +202,32 @@ func PlaySongInPlaylist(ctx *gctx.Context, client *spotify.Client, context *spot
}) })
if e != nil { if e != nil {
if isNoActiveError(e) { if isNoActiveError(e) {
err := activateDevice(ctx, client) deviceID, err := activateDevice(ctx, client)
if err != nil { if err != nil {
return err return err
} }
err = client.PlayOpt(ctx, &spotify.PlayOptions{ err = client.PlayOpt(ctx, &spotify.PlayOptions{
PlaybackOffset: &spotify.PlaybackOffset{Position: offset}, PlaybackOffset: &spotify.PlaybackOffset{Position: offset},
PlaybackContext: context, PlaybackContext: context,
DeviceID: &deviceID,
}) })
if err != nil {
if isNoActiveError(err) {
deviceID, err := activateDevice(ctx, client)
if err != nil {
return err
}
err = client.PlayOpt(ctx, &spotify.PlayOptions{
PlaybackOffset: &spotify.PlaybackOffset{Position: offset},
PlaybackContext: context,
DeviceID: &deviceID,
})
if err != nil {
return err
}
}
}
err = client.Play(ctx) err = client.Play(ctx)
if err != nil { if err != nil {
return err return err
@ -216,27 +242,53 @@ func PlaySongInPlaylist(ctx *gctx.Context, client *spotify.Client, context *spot
func PlayLikedSongs(ctx *gctx.Context, client *spotify.Client, position int) error { func PlayLikedSongs(ctx *gctx.Context, client *spotify.Client, position int) error {
err := ClearRadio(ctx, client) err := ClearRadio(ctx, client)
if err != nil { if err != nil {
fmt.Println(err.Error())
return err return err
} }
playlist, err := GetRadioPlaylist(ctx, client) playlist, err := GetRadioPlaylist(ctx, client)
if err != nil { if err != nil {
fmt.Println(err.Error())
return err return err
} }
songs, err := client.CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset(position)) songs, err := client.CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset(position))
if err != nil { if err != nil {
fmt.Println(err.Error())
return err return err
} }
to_add := []spotify.ID{} to_add := []spotify.ID{}
for _, song := range songs.Tracks { for _, song := range songs.Tracks {
to_add = append(to_add, song.ID) to_add = append(to_add, song.ID)
} }
client.AddTracksToPlaylist(ctx, playlist.ID, to_add...) fmt.Println(len(to_add))
client.PlayOpt(ctx, &spotify.PlayOptions{ _, err = client.AddTracksToPlaylist(ctx, playlist.ID, to_add...)
if err != nil {
fmt.Println(err.Error())
return err
}
err = client.PlayOpt(ctx, &spotify.PlayOptions{
PlaybackContext: &playlist.URI, PlaybackContext: &playlist.URI,
PlaybackOffset: &spotify.PlaybackOffset{ PlaybackOffset: &spotify.PlaybackOffset{
Position: 0, Position: 0,
}, },
}) })
if err != nil {
if isNoActiveError(err) {
deviceID, err := activateDevice(ctx, client)
if err != nil {
return err
}
err = client.PlayOpt(ctx, &spotify.PlayOptions{
PlaybackContext: &playlist.URI,
PlaybackOffset: &spotify.PlaybackOffset{
Position: 0,
},
DeviceID: &deviceID,
})
if err != nil {
return err
}
}
}
for page := 2; page <= 5; page++ { for page := 2; page <= 5; page++ {
songs, err := client.CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset((50*(page-1))+position)) songs, err := client.CurrentUsersTracks(ctx, spotify.Limit(50), spotify.Offset((50*(page-1))+position))
if err != nil { if err != nil {
@ -349,13 +401,32 @@ func RadioGivenSong(ctx *gctx.Context, client *spotify.Client, song_id spotify.I
if pos != 0 { if pos != 0 {
pos = pos + int(delay) pos = pos + int(delay)
} }
client.PlayOpt(ctx, &spotify.PlayOptions{ err = client.PlayOpt(ctx, &spotify.PlayOptions{
PlaybackContext: &radioPlaylist.URI, PlaybackContext: &radioPlaylist.URI,
PlaybackOffset: &spotify.PlaybackOffset{ PlaybackOffset: &spotify.PlaybackOffset{
Position: 0, Position: 0,
}, },
PositionMs: pos, PositionMs: pos,
}) })
if err != nil {
if isNoActiveError(err) {
deviceID, err := activateDevice(ctx, client)
if err != nil {
return err
}
err = client.PlayOpt(ctx, &spotify.PlayOptions{
PlaybackContext: &radioPlaylist.URI,
PlaybackOffset: &spotify.PlaybackOffset{
Position: 0,
},
DeviceID: &deviceID,
PositionMs: pos,
})
if err != nil {
return err
}
}
}
err = client.Repeat(ctx, "context") err = client.Repeat(ctx, "context")
if err != nil { if err != nil {
return err return err
@ -393,11 +464,10 @@ func Radio(ctx *gctx.Context, client *spotify.Client) error {
seed_song = current_song.Item.SimpleTrack seed_song = current_song.Item.SimpleTrack
} }
if current_song.Item == nil { if current_song.Item == nil {
err := activateDevice(ctx, client) _, err := activateDevice(ctx, client)
if err != nil { if err != nil {
return err return err
} }
tracks, err := client.CurrentUsersTracks(ctx, spotify.Limit(10)) tracks, err := client.CurrentUsersTracks(ctx, spotify.Limit(10))
if err != nil { if err != nil {
return err return err
@ -623,6 +693,18 @@ func Next(ctx *gctx.Context, client *spotify.Client, amt int) error {
if amt == 1 { if amt == 1 {
err := client.Next(ctx) err := client.Next(ctx)
if err != nil { if err != nil {
if isNoActiveError(err) {
deviceId, err := activateDevice(ctx, client)
if err != nil {
return err
}
err = client.NextOpt(ctx, &spotify.PlayOptions{
DeviceID: &deviceId,
})
if err != nil {
return err
}
}
return err return err
} }
return nil return nil
@ -811,7 +893,7 @@ func SetDevice(ctx *gctx.Context, client *spotify.Client, device spotify.PlayerD
if err != nil { if err != nil {
return err return err
} }
err = activateDevice(ctx, client) _, err = activateDevice(ctx, client)
if err != nil { if err != nil {
return err return err
} }
@ -951,15 +1033,29 @@ func RadioGivenList(ctx *gctx.Context, client *spotify.Client, song_ids []spotif
if err != nil { if err != nil {
return err return err
} }
client.PlayOpt(ctx, &spotify.PlayOptions{ err = client.PlayOpt(ctx, &spotify.PlayOptions{
PlaybackContext: &radioPlaylist.URI, PlaybackContext: &radioPlaylist.URI,
PlaybackOffset: &spotify.PlaybackOffset{ PlaybackOffset: &spotify.PlaybackOffset{
Position: 0, Position: 0,
}, },
}) })
err = client.Repeat(ctx, "context")
if err != nil { if err != nil {
return err if isNoActiveError(err) {
deviceId, err := activateDevice(ctx, client)
if err != nil {
return err
}
err = client.PlayOpt(ctx, &spotify.PlayOptions{
PlaybackContext: &radioPlaylist.URI,
PlaybackOffset: &spotify.PlaybackOffset{
Position: 0,
},
DeviceID: &deviceId,
})
if err != nil {
return err
}
}
} }
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
id := rand.Intn(len(recomendationIds)-2) + 1 id := rand.Intn(len(recomendationIds)-2) + 1
@ -986,31 +1082,54 @@ func RadioGivenList(ctx *gctx.Context, client *spotify.Client, song_ids []spotif
return nil return nil
} }
func activateDevice(ctx *gctx.Context, client *spotify.Client) error { func activateDevice(ctx *gctx.Context, client *spotify.Client) (spotify.ID, error) {
var device *spotify.PlayerDevice
configDir, _ := os.UserConfigDir() configDir, _ := os.UserConfigDir()
if _, err := os.Stat(filepath.Join(configDir, "gospt/device.json")); err == nil { if _, err := os.Stat(filepath.Join(configDir, "gospt/device.json")); err == nil {
deviceFile, err := os.Open(filepath.Join(configDir, "gospt/device.json")) deviceFile, err := os.Open(filepath.Join(configDir, "gospt/device.json"))
if err != nil { if err != nil {
return err return "", err
} }
defer deviceFile.Close() defer deviceFile.Close()
deviceValue, err := io.ReadAll(deviceFile) deviceValue, err := io.ReadAll(deviceFile)
if err != nil { if err != nil {
return err return "", err
} }
var device *spotify.PlayerDevice
err = json.Unmarshal(deviceValue, &device) err = json.Unmarshal(deviceValue, &device)
if err != nil { if err != nil {
return err return "", err
} }
err = client.TransferPlayback(ctx, device.ID, true) err = client.TransferPlayback(ctx, device.ID, true)
if err != nil { if err != nil {
return err return "", err
} }
} else { } else {
fmt.Println("YOU MUST RUN gospt setdevice FIRST") fmt.Println("YOU MUST RUN gospt setdevice FIRST")
} }
return nil return device.ID, nil
}
func getDefaultDevice(ctx *gctx.Context, client *spotify.Client) (spotify.ID, error) {
configDir, _ := os.UserConfigDir()
if _, err := os.Stat(filepath.Join(configDir, "gospt/device.json")); err == nil {
deviceFile, err := os.Open(filepath.Join(configDir, "gospt/device.json"))
if err != nil {
return "", err
}
defer deviceFile.Close()
deviceValue, err := io.ReadAll(deviceFile)
if err != nil {
return "", err
}
var device *spotify.PlayerDevice
err = json.Unmarshal(deviceValue, &device)
if err != nil {
return "", err
}
return device.ID, nil
} else {
return "", err
}
} }
func GetRadioPlaylist(ctx *gctx.Context, client *spotify.Client) (*spotify.FullPlaylist, error) { func GetRadioPlaylist(ctx *gctx.Context, client *spotify.Client) (*spotify.FullPlaylist, error) {

View File

@ -87,7 +87,7 @@ func (m *mainModel) PlayRadio() {
case spotify.SimplePlaylist: case spotify.SimplePlaylist:
go HandlePlaylistRadio(m.ctx, m.client, selectedItem.(spotify.SimplePlaylist)) go HandlePlaylistRadio(m.ctx, m.client, selectedItem.(spotify.SimplePlaylist))
return return
case spotify.SavedTrackPage: case *spotify.SavedTrackPage:
go HandleLibraryRadio(m.ctx, m.client) go HandleLibraryRadio(m.ctx, m.client)
return return
case spotify.SimpleAlbum: case spotify.SimpleAlbum: