aboutsummaryrefslogtreecommitdiffstats
path: root/lfmclient.go
diff options
context:
space:
mode:
authorThibaut Horel <thibaut.horel@gmail.com>2017-06-19 19:21:58 -0400
committerThibaut Horel <thibaut.horel@gmail.com>2017-06-19 19:21:58 -0400
commit458294c8de2af24313d5d3e430482fb187128434 (patch)
treef36d9a932502098841ca44fc17d7446fa591d6a0 /lfmclient.go
parenteb41a250b7caa464e6f6d7297416bc8bd8d72a8c (diff)
downloadlastfm-api-458294c8de2af24313d5d3e430482fb187128434.tar.gz
Make lastfm scrobble imports cleaner and more efficient
Diffstat (limited to 'lfmclient.go')
-rw-r--r--lfmclient.go131
1 files changed, 85 insertions, 46 deletions
diff --git a/lfmclient.go b/lfmclient.go
index c845b7d..bbc0492 100644
--- a/lfmclient.go
+++ b/lfmclient.go
@@ -28,6 +28,11 @@ type Date struct {
Uts string
}
+func (d *Date) ToTime() time.Time {
+ ts, _ := strconv.Atoi(d.Uts)
+ return time.Unix(int64(ts), 0)
+}
+
type PageAttrs struct {
TotalPages string
Total string
@@ -55,6 +60,19 @@ type TrackInfo struct {
Listeners string
}
+type LovedTrack struct {
+ Name string
+ Mbid string
+ Url string
+ Date Date
+ Artist ArtistInfo
+ Images []Image
+}
+
+type Playing struct {
+ NowPlaying string
+}
+
type RecentTrack struct {
Name string
Mbid string
@@ -67,8 +85,9 @@ type RecentTrack struct {
Name string `json:"#text"`
Mbid string
}
- Images []Image `json:"image"`
- Date Date
+ Images []Image `json:"image"`
+ Date Date
+ Playing `json:"@attr"`
}
func (app *App) LfmQuery(payload map[string]string) []byte {
@@ -118,6 +137,58 @@ func (app *App) TrackInfo(artist, name string) TrackInfo {
return dst["track"]
}
+type RecentTracks struct {
+ dst map[string]struct {
+ Attrs PageAttrs `json:"@attr"`
+ Tracks []RecentTrack `json:"track"`
+ }
+ payload map[string]string
+ *App
+}
+
+func RecentTrackToScrobble(r *RecentTrack, s *Session) Scrobble {
+ scrobble := Scrobble{
+ Artist: NewCorrectable(r.Artist.Name),
+ Album: NewCorrectable(r.Album.Name),
+ TrackName: NewCorrectable(r.Name),
+ Mbid: r.Mbid,
+ Time: r.Date.ToTime(),
+ UserId: s.UserId,
+ SessionKey: s.Key,
+ Image: GetImage(r.Images, "medium"),
+ }
+ return scrobble
+}
+
+func NewRecentTracks(name string, from, to time.Time, app *App) *RecentTracks {
+ rt := &RecentTracks{App: app}
+ rt.payload = map[string]string{
+ "method": "user.getRecentTracks",
+ "limit": "200",
+ "user": name,
+ "to": strconv.Itoa(int(to.Unix())),
+ }
+ if from.IsZero() {
+ rt.payload["from"] = "0"
+ } else {
+ rt.payload["from"] = strconv.Itoa(int(from.Unix()))
+ }
+ return rt
+}
+
+func (rt *RecentTracks) Next() []RecentTrack {
+ r := rt.App.LfmQuery(rt.payload)
+ json.Unmarshal(r, &rt.dst)
+ tracks := rt.dst["recenttracks"].Tracks
+ if len(tracks) > 0 {
+ d := tracks[len(tracks)-1].Date
+ if d.Uts != "" && d.Uts != "0" {
+ rt.payload["to"] = d.Uts
+ }
+ }
+ return tracks
+}
+
func (app *App) ImportRecentTracks(user *User) {
s := &Session{
UserId: user.Id,
@@ -128,77 +199,45 @@ func (app *App) ImportRecentTracks(user *User) {
}
app.PutSession(s)
i := app.NewImport(user.LfmName)
- payload := map[string]string{
- "method": "user.getRecentTracks",
- "limit": "200",
- "user": user.LfmName,
- "to": strconv.Itoa(int(i.To.Unix())),
- }
- if i.From.IsZero() {
- payload["from"] = "0"
- } else {
- payload["from"] = strconv.Itoa(int(i.From.Unix()))
- }
- var dst map[string]struct {
- Attrs PageAttrs `json:"@attr"`
- Tracks []RecentTrack `json:"track"`
- }
+ rt := NewRecentTracks(user.LfmName, i.From, i.To, app)
scrobbles := make([]Scrobble, 0, 200)
- var st time.Time
- for {
+ for tracks := rt.Next(); len(tracks) > 0; tracks = rt.Next() {
scrobbles = scrobbles[:0]
- if !i.LastFetch.IsZero() {
- payload["to"] = strconv.Itoa(int(i.LastFetch.Unix()))
- }
- r := app.LfmQuery(payload)
- json.Unmarshal(r, &dst)
- tracks := dst["recenttracks"].Tracks
- if len(tracks) == 0 {
- i.Done = true
- break
- }
for _, t := range tracks {
- ts, _ := strconv.Atoi(t.Date.Uts)
- if ts == 0 {
+ if t.NowPlaying == "true" {
continue
}
- st = time.Unix(int64(ts), 0)
- scrobble := Scrobble{
- Artist: NewCorrectable(t.Artist.Name),
- Album: NewCorrectable(t.Album.Name),
- TrackName: NewCorrectable(t.Name),
- Mbid: t.Mbid,
- Time: st,
- UserId: user.Id,
- SessionKey: s.Key,
- Image: GetImage(t.Images, "medium"),
- }
+ scrobble := RecentTrackToScrobble(&t, s)
app.GetScrobbleSong(&scrobble)
scrobbles = append(scrobbles, scrobble)
}
+ if len(scrobbles) == 0 {
+ break
+ }
if err := app.PutScrobbles(scrobbles); err != nil {
log.Println(err)
}
- i.LastFetch = st
+ i.LastFetch = scrobbles[len(scrobbles)-1].Time
i.Count += len(scrobbles)
if err := app.SaveImport(i); err != nil {
log.Println(err)
}
}
+ i.Done = true
if err := app.SaveImport(i); err != nil {
log.Println(err)
}
}
-func (app *App) LovedTracks(user string) []TrackInfo {
+func (app *App) LovedTracks(user string) []LovedTrack {
r := app.LfmQuery(map[string]string{
"method": "user.getLovedTracks",
"limit": "100",
"user": user,
})
var dst map[string]struct {
- Attrs PageAttrs `json:"@attr"`
- Tracks []TrackInfo `json:"track"`
+ Attrs PageAttrs `json:"@attr"`
+ Tracks []LovedTrack `json:"track"`
}
json.Unmarshal(r, &dst)
root := dst["lovedtracks"]