diff --git a/player.go b/player.go index fc7a903..b03c3b8 100644 --- a/player.go +++ b/player.go @@ -32,6 +32,14 @@ func NewMediaFromEpisode(episode *metadatapb.Episode) *Media { return &Media{track: nil, episode: episode} } +func (te Media) Id() SpotifyId { + if te.track != nil { + return SpotifyIdFromGid(SpotifyIdTypeTrack, te.track.GetGid()) + } else { + return SpotifyIdFromGid(SpotifyIdTypeEpisode, te.episode.GetGid()) + } +} + func (te Media) IsTrack() bool { return te.track != nil } diff --git a/player/player.go b/player/player.go index b208f46..8af3858 100644 --- a/player/player.go +++ b/player/player.go @@ -31,8 +31,6 @@ const ( const MaxStateVolume = 65535 -const DisableCheckMediaRestricted = true - const CdnUrlQuarantineDuration = 15 * time.Minute func ptr[T any](v T) *T { @@ -539,6 +537,38 @@ func calculateNormalisationFactor(params *audiofilespb.NormalizationParams, preg return normalisationFactor } +func (p *Player) getUnrestrictedTrack(ctx context.Context, spotId librespot.SpotifyId) (*metadatapb.Track, error) { + var trackMeta metadatapb.Track + err := p.sp.ExtendedMetadataSimple(ctx, spotId, extmetadatapb.ExtensionKind_TRACK_V4, &trackMeta) + if err != nil { + return nil, fmt.Errorf("failed getting track metadata: %w", err) + } + + media := librespot.NewMediaFromTrack(&trackMeta) + if !isMediaRestricted(media, *p.countryCode) { + return &trackMeta, nil + } + + for _, alt := range trackMeta.Alternative { + media = librespot.NewMediaFromTrack(alt) + if !isMediaRestricted(media, *p.countryCode) { + // Clear alternatives to avoid confusion + trackMeta.Alternative = nil + + // The alternative track does not have all fields set, copy them over + // to the original track metadata. + trackMeta.Gid = alt.Gid + trackMeta.File = alt.File + trackMeta.Preview = alt.Preview + trackMeta.OriginalAudio = alt.OriginalAudio + return &trackMeta, nil + } + } + + // We tried all alternatives, still restricted + return nil, librespot.ErrMediaRestricted +} + func (p *Player) NewStream(ctx context.Context, client *http.Client, spotId librespot.SpotifyId, bitrate int, mediaPosition int64) (*Stream, error) { log := p.log.WithField("uri", spotId.Uri()) @@ -551,16 +581,13 @@ func (p *Player) NewStream(ctx context.Context, client *http.Client, spotId libr var media *librespot.Media var file *metadatapb.AudioFile if spotId.Type() == librespot.SpotifyIdTypeTrack { - var trackMeta metadatapb.Track - err := p.sp.ExtendedMetadataSimple(ctx, spotId, extmetadatapb.ExtensionKind_TRACK_V4, &trackMeta) + trackMeta, err := p.getUnrestrictedTrack(ctx, spotId) if err != nil { - return nil, fmt.Errorf("failed getting track metadata: %w", err) + return nil, err } - media = librespot.NewMediaFromTrack(&trackMeta) - if !DisableCheckMediaRestricted && isMediaRestricted(media, *p.countryCode) { - return nil, librespot.ErrMediaRestricted - } + media = librespot.NewMediaFromTrack(trackMeta) + spotId = media.Id() var audioFilesResp audiofilespb.AudioFilesExtensionResponse err = p.sp.ExtendedMetadataSimple(ctx, spotId, extmetadatapb.ExtensionKind_AUDIO_FILES, &audioFilesResp) @@ -601,7 +628,7 @@ func (p *Player) NewStream(ctx context.Context, client *http.Client, spotId libr } media = librespot.NewMediaFromEpisode(&episodeMeta) - if !DisableCheckMediaRestricted && isMediaRestricted(media, *p.countryCode) { + if isMediaRestricted(media, *p.countryCode) { return nil, librespot.ErrMediaRestricted }