diff options
| author | Thibaut Horel <thibaut.horel@gmail.com> | 2017-06-17 12:49:28 -0400 |
|---|---|---|
| committer | Thibaut Horel <thibaut.horel@gmail.com> | 2017-06-17 12:49:28 -0400 |
| commit | 858de1edf50cc1128f6b621a5413b2975ca446eb (patch) | |
| tree | 09cec370362844ac9a3fc7c6a128808f632894c7 | |
| parent | 060b315f74f437fe36175c4ddb52379d29808d64 (diff) | |
| download | lastfm-api-858de1edf50cc1128f6b621a5413b2975ca446eb.tar.gz | |
Clean fecthing of song metadata from Last.fm
| -rw-r--r-- | apiv1.go | 17 | ||||
| -rw-r--r-- | data.go | 35 | ||||
| -rw-r--r-- | lfmclient.go | 129 |
3 files changed, 113 insertions, 68 deletions
@@ -180,7 +180,7 @@ func (app *App) scrobbleHandler(w http.ResponseWriter, r *http.Request) { scrobbles, _ := parseScrobbles(r.Form, session) for i, s := range scrobbles { - app.GetSong(&s) + app.GetScrobbleSong(&s) scrobbles[i] = s } @@ -211,6 +211,19 @@ func parseNowPlaying(values url.Values) (Scrobble, error) { return scrobble, nil } +func (app *App) GetScrobbleSong(s *Scrobble) { + song := Song{ + Artist: s.Artist.Name, + Album: s.Album.Name, + Name: s.TrackName.Name, + TrackNumber: s.TrackNumber, + Duration: s.Duration * 1000, + Mbid: s.Mbid, + } + app.GetSong(&song) + s.SongId = song.Id +} + func (app *App) nowPlayingHandler(w http.ResponseWriter, r *http.Request) { session, err := app.GetSession(r.FormValue("s")) if err != nil { @@ -221,7 +234,7 @@ func (app *App) nowPlayingHandler(w http.ResponseWriter, r *http.Request) { s, err := parseNowPlaying(r.Form) s.SessionKey = session.Key s.UserId = session.UserId - app.GetSong(&s) + app.GetScrobbleSong(&s) if err := app.PutNowPlaying(s); err != nil { log.Println(err) fmt.Fprintln(w, "Failed Database") @@ -35,6 +35,17 @@ type Session struct { Subscriber int64 `json:"subscriber" xml:"subscriber"` } +type Song struct { + Id int + Artist string + Album string + Name string + TrackNumber int + Duration int + Mbid string + Image string +} + type DataStore interface { PutSession(*Session) error GetSession(key string) (*Session, error) @@ -42,8 +53,9 @@ type DataStore interface { PutNowPlaying(s Scrobble) error NowPlaying(userId int) *Scrobble RecentScrobbles(userId int) []*Scrobble - GetSongId(artist, album, name string) (int, error) - InsertSong(s *Scrobble) (int, error) + + GetSongId(s *Song) error + InsertSong(s *Song) error GetScrobblingUser(lfmName string) (int, string, error) GetUser(u *User) error @@ -166,28 +178,23 @@ func (store *SqlStore) NowPlaying(userId int) *Scrobble { return scrobble } -func (store *SqlStore) GetSongId(artist, album, song string) (int, error) { +func (store *SqlStore) GetSongId(s *Song) error { query := ` SELECT song_id FROM songs WHERE artist=$1 AND album=$2 AND name=$3 ` - var id int - row := store.QueryRow(query, artist, album, song) - err := row.Scan(&id) - return id, err - + row := store.QueryRow(query, s.Artist, s.Album, s.Name) + return row.Scan(&s.Id) } -func (store *SqlStore) InsertSong(s *Scrobble) (int, error) { +func (store *SqlStore) InsertSong(s *Song) error { query := ` INSERT INTO songs (artist, album, name, track_number, duration, mbid, image) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING song_id` - var id int - row := store.QueryRow(query, s.Artist, s.Album, s.TrackName, s.TrackNumber, - s.Duration*1000, s.Mbid, s.Image) - err := row.Scan(&id) - return id, err + row := store.QueryRow(query, s.Artist, s.Album, s.Name, s.TrackNumber, + s.Duration, s.Mbid, s.Image) + return row.Scan(&s.Id) } func (store *SqlStore) InsertUser(user *User) error { diff --git a/lfmclient.go b/lfmclient.go index 9c500b7..41ecd37 100644 --- a/lfmclient.go +++ b/lfmclient.go @@ -2,35 +2,41 @@ package main import ( "encoding/json" + "fmt" "io/ioutil" "log" "net/http" - "strconv" ) -type AlbumImage struct { +type Image struct { Size string `json:"size"` Href string `json:"#text"` } -func (a AlbumInfo) GetImage(size string) string { - images := a.Images - for _, image := range images { - if image.Size == size { - return image.Href - } - } - return "https://lastfm-img2.akamaized.net/i/u/64s/4128a6eb29f94943c9d206c08e625904.png" +type AlbumInfo struct { + Images []Image `json:"image"` + Mbid string + Name string `json:"title"` + Url string + Position `json:"@attr"` } -type AlbumInfo struct { - Images []AlbumImage `json:"image"` - Mbid string `json:"mbid"` - Name string `json:"title"` +type Date struct { + Date string `json:"#text"` + Uts string +} + +type PageAttrs struct { + TotalPages string + Total string + Page string + User string } type ArtistInfo struct { - Name string `json:"name"` + Name string + Mbid string + Url string } type Position struct { @@ -38,12 +44,11 @@ type Position struct { } type TrackInfo struct { - Name string `json:"name"` - Mbid string `json:"mbid"` - Duration string `json:"duration"` - Artist ArtistInfo `json:"artist"` - Album AlbumInfo `json:"album"` - Position `json:"@attr"` + Name string + Mbid string + Duration string + Artist ArtistInfo + Album AlbumInfo } func (app *App) LfmQuery(payload map[string]string) []byte { @@ -57,10 +62,21 @@ func (app *App) LfmQuery(payload map[string]string) []byte { r.URL.RawQuery = values.Encode() resp, _ := http.DefaultClient.Do(r) body, _ := ioutil.ReadAll(resp.Body) + resp.Body.Close() return body } -func (app *App) AlbumImage(artist, album string) string { +func (a AlbumInfo) GetImage(size string) string { + images := a.Images + for _, image := range images { + if image.Size == size { + return image.Href + } + } + return "https://lastfm-img2.akamaized.net/i/u/64s/4128a6eb29f94943c9d206c08e625904.png" +} + +func (app *App) AlbumInfo(artist, album string) AlbumInfo { r := app.LfmQuery(map[string]string{ "method": "album.getInfo", "artist": artist, @@ -68,10 +84,10 @@ func (app *App) AlbumImage(artist, album string) string { }) var dst map[string]AlbumInfo json.Unmarshal(r, &dst) - return dst["album"].GetImage("medium") + return dst["album"] } -func (app *App) TrackInfo(artist, name string) *Scrobble { +func (app *App) TrackInfo(artist, name string) TrackInfo { r := app.LfmQuery(map[string]string{ "method": "track.getInfo", "artist": artist, @@ -80,40 +96,49 @@ func (app *App) TrackInfo(artist, name string) *Scrobble { }) var dst map[string]TrackInfo json.Unmarshal(r, &dst) - track := dst["track"] - duration, _ := strconv.Atoi(track.Duration) - position, _ := strconv.Atoi(track.TrackNumber) - s := &Scrobble{ - Artist: NewCorrectable(track.Artist.Name), - Album: NewCorrectable(track.Album.Name), - TrackName: NewCorrectable(track.Name), - Duration: duration * 1000, - TrackNumber: position, - Mbid: track.Mbid, - Image: track.Album.GetImage("medium"), - } - return s + return dst["track"] +} + +func (app *App) RecentTracks(user string) { + r := app.LfmQuery(map[string]string{ + "method": "user.getRecentTracks", + "limit": "10", + "user": user, + }) + fmt.Println(string(r)) +} +func (app *App) LovedTracks(user string) []TrackInfo { + 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"` + } + json.Unmarshal(r, &dst) + root := dst["lovedtracks"] + tracks := root.Tracks + return tracks } -func (app *App) GetSong(s *Scrobble) { - var err error - if s.Album.Name != "" { - id, _ := app.GetSongId(s.Artist.Name, s.Album.Name, s.TrackName.Name) - if id == 0 { - s.Image = app.AlbumImage(s.Artist.Name, s.Album.Name) - id, err = app.InsertSong(s) - if err != nil { +func (app *App) GetSong(s *Song) { + if s.Album != "" { + if app.GetSongId(s) != nil { + if s.Image == "" { + s.Image = app.AlbumInfo(s.Artist, s.Album).GetImage("medium") + } + if err := app.InsertSong(s); err != nil { log.Println(err) } } - s.SongId = id } else { - s2 := app.TrackInfo(s.Artist.Name, s.TrackName.Name) - id, err := app.InsertSong(s2) - if err != nil { - log.Println(err) - } - s.SongId = id + t := app.TrackInfo(s.Artist, s.Name) + s.Album = t.Album.Name + s.Mbid = t.Mbid + s.Image = t.Album.GetImage("medium") + app.InsertSong(s) } } |
