-
Notifications
You must be signed in to change notification settings - Fork 0
/
spotify.go
130 lines (109 loc) · 3.33 KB
/
spotify.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package spotify
import (
"context"
"github.com/golang/glog"
)
type Spotify struct {
connector *connector
cache Cache
}
func New(ctx context.Context, market string) (*Spotify, error) {
c, err := newConnector(ctx, market)
if err != nil {
return nil, err
}
return &Spotify{
connector: c,
cache: newCache(),
}, nil
}
func (s *Spotify) AddToPlaylist(ctx context.Context, playlistId string, track *ImmutableSpotifyTrack) error {
// Add to cache only if playlist is already cached (this is to avoid creating cache before list)
if s.cache.IsCached(playlistId) {
err := s.cache.Add(playlistId, track)
if err != nil {
return err
}
}
err := s.connector.addToPlaylist(ctx, playlistId, track.Id())
if err != nil {
// Try to remove what was added to cache in case of error
err2 := s.cache.Remove(playlistId, track)
if err2 != nil {
glog.Errorf("Error returned from cache when removing incorrectly added track: %v", err2)
}
return err
}
return nil
}
func (s *Spotify) RemoveFromPlaylist(ctx context.Context, playlistId string, track *ImmutableSpotifyTrack) error {
err := s.cache.Remove(playlistId, track)
if err != nil {
return err
}
err = s.connector.removeFromPlaylist(ctx, playlistId, track.Id())
if err != nil {
// Try to add what was removed to cache in case of error
err2 := s.cache.Add(playlistId, track)
if err2 != nil {
glog.Errorf("Error returned from cache when adding incorrectly removed track: %v", err2)
}
return err
}
return nil
}
func (s *Spotify) ListLiked(ctx context.Context) ([]*ImmutableSpotifyTrack, error) {
tracks, err := s.connector.listLiked(ctx)
if err != nil {
return nil, err
}
// Not using cache for liked songs for now.
result := make([]*ImmutableSpotifyTrack, len(tracks))
for i := range tracks {
result[i] = tracks[i].immutable()
}
glog.V(2).Infof("ListLiked: %v", tracks)
return result, nil
}
func (s *Spotify) ListPlaylist(ctx context.Context, playlistId string) ([]*ImmutableSpotifyTrack, error) {
if s.cache.IsCached(playlistId) {
glog.V(1).Infof("Found cached tracks for %v, not connecting to spotify.", playlistId)
return s.cache.Get(playlistId), nil
}
glog.V(1).Infof("Found 0 cached tracks for %v, connecting to spotify.", playlistId)
//Ignoring the error as the method updates cache
return s.ListPlaylistWithFilter(ctx, playlistId, func(s SpotifyTrack) bool { return true })
}
func (s *Spotify) ListPlaylistWithFilter(ctx context.Context, playlistId string, filter func(SpotifyTrack) bool) ([]*ImmutableSpotifyTrack, error) {
tracks, err := s.connector.listPlaylist(ctx, playlistId)
if err != nil {
return nil, err
}
// Add songs to cache
cached := make([]*ImmutableSpotifyTrack, len(tracks))
result := make([]*ImmutableSpotifyTrack, 0)
for i := range tracks {
imm := tracks[i].immutable()
cached[i] = imm
if filter(tracks[i]) {
result = append(result, imm)
}
}
s.cache.ReplaceAll(playlistId, cached)
if err != nil {
return nil, err
}
glog.V(2).Infof("ListPlaylistWithFilter: %v", tracks)
return result, nil
}
func (s *Spotify) FindTracks(ctx context.Context, query string) ([]*ImmutableSpotifyTrack, error) {
tracks, err := s.connector.findTracks(ctx, query)
if err != nil {
return nil, err
}
result := make([]*ImmutableSpotifyTrack, len(tracks))
for i := range tracks {
result[i] = tracks[i].immutable()
}
return result, nil
}