aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--apiv1.go41
-rw-r--r--data.go32
-rw-r--r--migrations/20170613221502_np.sql21
-rw-r--r--static/np.gifbin0 -> 1643 bytes
-rw-r--r--static/np2.gifbin0 -> 1274 bytes
-rw-r--r--static/style.css7
-rw-r--r--templates/index.tmpl15
-rw-r--r--web.go13
9 files changed, 116 insertions, 17 deletions
diff --git a/Makefile b/Makefile
index 5d95879..a452c47 100644
--- a/Makefile
+++ b/Makefile
@@ -16,10 +16,10 @@ watch:
watchman-make -p '*.go' 'templates/*.tmpl' -t all
up:
- goose -dir migrations postgres "$(DB)" up
+ goose -dir migrations postgres $(DB) up
down:
- goose -dir migrations postgres "$(DB)" down
+ goose -dir migrations postgres $(DB) down
status:
goose -dir migrations postgres $(DB) status
diff --git a/apiv1.go b/apiv1.go
index e555a18..1f96819 100644
--- a/apiv1.go
+++ b/apiv1.go
@@ -177,15 +177,14 @@ func (app *App) scrobbleHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "BADSESSION")
return
}
- scrobbles, _ := parseScrobbles(r.Form, session)
+ scrobbles, _ := parseScrobbles(r.Form, session)
for i, s := range scrobbles {
app.GetSong(&s)
scrobbles[i] = s
}
- err = app.PutScrobbles(scrobbles)
- if err != nil {
+ if err := app.PutScrobbles(scrobbles); err != nil {
log.Println(err)
fmt.Fprintln(w, "Failed Database")
return
@@ -193,10 +192,40 @@ func (app *App) scrobbleHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "OK")
}
+func parseNowPlaying(values url.Values) (Scrobble, error) {
+ var scrobble Scrobble
+ scrobble.TrackName = NewCorrectable(values.Get("t"))
+ scrobble.Artist = NewCorrectable(values.Get("a"))
+ scrobble.Album = NewCorrectable(values.Get("b"))
+ scrobble.Mbid = values.Get("m")
+ if tn, err := strconv.Atoi(values.Get("n")); err != nil {
+ return scrobble, errors.New("Could not parse track number")
+ } else {
+ scrobble.TrackNumber = tn
+ }
+ if duration, err := strconv.Atoi(values.Get("l")); err != nil {
+ return scrobble, errors.New("Could not parse duration")
+ } else {
+ scrobble.Duration = duration
+ }
+ return scrobble, nil
+}
+
func (app *App) nowPlayingHandler(w http.ResponseWriter, r *http.Request) {
- if _, err := app.GetSession(r.FormValue("s")); err != nil {
+ session, err := app.GetSession(r.FormValue("s"))
+ if err != nil {
+ log.Println(err)
fmt.Fprintln(w, "BADSESSION")
- } else {
- fmt.Fprintln(w, "OK")
+ return
+ }
+ s, err := parseNowPlaying(r.Form)
+ s.SessionKey = session.Key
+ s.UserId = session.UserId
+ app.GetSong(&s)
+ if err := app.PutNowPlaying(s); err != nil {
+ log.Println(err)
+ fmt.Fprintln(w, "Failed Database")
+ return
}
+ fmt.Fprintln(w, "OK")
}
diff --git a/data.go b/data.go
index a447516..b97d4a4 100644
--- a/data.go
+++ b/data.go
@@ -39,6 +39,8 @@ type DataStore interface {
PutSession(*Session) error
GetSession(key string) (*Session, error)
PutScrobbles([]Scrobble) error
+ PutNowPlaying(s Scrobble) error
+ NowPlaying(userId int) *Scrobble
RecentScrobbles(userId int) []*Scrobble
GetSongId(artist, album, name string) (int, error)
InsertSong(s *Scrobble) (int, error)
@@ -111,6 +113,22 @@ func (store *SqlStore) PutScrobbles(scrobbles []Scrobble) error {
return tx.Commit()
}
+func (store *SqlStore) PutNowPlaying(s Scrobble) error {
+ query := `
+ INSERT INTO now_playing
+ (artist, album_artist, track_name, album, track_number, duration,
+ mbid, song_id, session_key, user_id)
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
+ ON CONFLICT (user_id) DO UPDATE
+ set artist=$1, album_artist=$2, track_name=$3, album=$4, track_number=$5,
+ duration=$6, mbid=$7, song_id=$8, session_key=$9, user_id=$10,
+ received=current_timestamp`
+
+ _, err := store.Exec(query, s.Artist, s.AlbumArtist, s.TrackName, s.Album,
+ s.TrackNumber, s.Duration, s.Mbid, s.SongId, s.SessionKey, s.UserId)
+ return err
+}
+
func (store *SqlStore) RecentScrobbles(userId int) []*Scrobble {
scrobbles := make([]*Scrobble, 0, 10)
query := `
@@ -134,6 +152,20 @@ func (store *SqlStore) RecentScrobbles(userId int) []*Scrobble {
return scrobbles
}
+func (store *SqlStore) NowPlaying(userId int) *Scrobble {
+ scrobble := new(Scrobble)
+ query := `
+ SELECT s.artist, s.album, s.track_name, s.received, songs.image, s.duration
+ FROM now_playing s
+ LEFT JOIN songs ON songs.song_id = s.song_id
+ WHERE user_id=$1`
+ row := store.QueryRow(query, userId)
+ row.Scan(&scrobble.Artist.Name, &scrobble.Album.Name,
+ &scrobble.TrackName.Name, &scrobble.Time, &scrobble.Image,
+ &scrobble.Duration)
+ return scrobble
+}
+
func (store *SqlStore) GetSongId(artist, album, song string) (int, error) {
query := `
SELECT song_id FROM songs
diff --git a/migrations/20170613221502_np.sql b/migrations/20170613221502_np.sql
new file mode 100644
index 0000000..7659555
--- /dev/null
+++ b/migrations/20170613221502_np.sql
@@ -0,0 +1,21 @@
+
+-- +goose Up
+-- SQL in section 'Up' is executed when this migration is applied
+CREATE TABLE IF NOT EXISTS now_playing (
+ artist text,
+ album_artist text,
+ track_name text,
+ album text,
+ track_number int,
+ duration int,
+ received timestamptz DEFAULT current_timestamp,
+ mbid text,
+ song_id int REFERENCES songs,
+ session_key text REFERENCES scrobbling_sessions,
+ user_id int UNIQUE REFERENCES users
+);
+
+-- +goose Down
+-- SQL section 'Down' is executed when this migration is rolled back
+DROP TABLE now_playing;
+
diff --git a/static/np.gif b/static/np.gif
new file mode 100644
index 0000000..7b53c2e
--- /dev/null
+++ b/static/np.gif
Binary files differ
diff --git a/static/np2.gif b/static/np2.gif
new file mode 100644
index 0000000..91abce7
--- /dev/null
+++ b/static/np2.gif
Binary files differ
diff --git a/static/style.css b/static/style.css
index c4d2db4..4072988 100644
--- a/static/style.css
+++ b/static/style.css
@@ -68,7 +68,7 @@ ul.scrobbles li:hover {
cursor: pointer;
}
-ul.scrobbles li img {
+ul.scrobbles li img.cover {
height: 40px;
margin-right: 16px;
border: 1px solid #C5CAE9;
@@ -82,6 +82,11 @@ ul.scrobbles li div {
line-height: 18px;
}
+ul.scrobbles li .time {
+ font-size: 12px;
+ color: #4f4f4f;
+}
+
ul.scrobbles li .album {
font-size: 12px;
color: #4f4f4f;
diff --git a/templates/index.tmpl b/templates/index.tmpl
index 2451c6b..1ab1726 100644
--- a/templates/index.tmpl
+++ b/templates/index.tmpl
@@ -1,21 +1,26 @@
{{template "header" . }}
<h2>Recent Listens</h2>
<ul class="scrobbles">
+ {{if .NowPlaying}} {{template "song" .NowPlaying}} {{end}}
{{- range .Scrobbles}}
+ {{template "song" .}}
+{{- end}}
+</ul>
+{{template "footer" }}
+
+{{define "song"}}
<li>
- <img src="{{or .Image "https://lastfm-img2.akamaized.net/i/u/64s/4128a6eb29f94943c9d206c08e625904.png"}}"/>
+ <img class="cover" src="{{or .Image "https://lastfm-img2.akamaized.net/i/u/64s/4128a6eb29f94943c9d206c08e625904.png"}}"/>
<div>
{{.Artist}} — {{.TrackName}}<br/>
<span class="album">in {{.Album}}</span>
</div>
<div class="like">
- <span class="album">{{ago .Time}}</span><br/>
+ <span class="time">{{.Time | ago}}</span><br/>
<span class="swap">
<i class="material-icons one">favorite_border</i>
<i class="material-icons two">favorite</i>
</span>
</div>
</li>
-{{- end}}
-</ul>
-{{template "footer" }}
+{{end}}
diff --git a/web.go b/web.go
index 31a8317..371ae9f 100644
--- a/web.go
+++ b/web.go
@@ -7,6 +7,7 @@ import (
"io/ioutil"
"log"
"net/http"
+ "time"
_ "github.com/lib/pq"
)
@@ -49,11 +50,17 @@ func (app *App) root(w http.ResponseWriter, r *http.Request) {
}
scrobbles := app.RecentScrobbles(se.UserId)
+ np := app.NowPlaying(se.UserId)
+ np.Image = "static/np2.gif"
+ if time.Since(np.Time) > time.Duration(np.Duration)*time.Second {
+ np = nil
+ }
app.Template.ExecuteTemplate(w, "index.tmpl", struct {
- Session *UserSession
- Scrobbles []*Scrobble
- }{se, scrobbles})
+ Session *UserSession
+ Scrobbles []*Scrobble
+ NowPlaying *Scrobble
+ }{se, scrobbles, np})
}
func (app *App) callback(w http.ResponseWriter, r *http.Request) {