add custom listenbrainz url support and make ui "consistent"

Co-authored-by: spezifisch <spezifisch@users.noreply.github.com>
Co-authored-by: Alex McGrath <amk@amk.ie>
This commit is contained in:
sentriz
2021-01-11 23:34:55 +00:00
committed by Senan Kelly
parent 4443d7d0f5
commit a18929ad01
8 changed files with 903 additions and 870 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -5,15 +5,9 @@
</div> </div>
<div class="block-right"> <div class="block-right">
<table id="stats" class="text-right"> <table id="stats" class="text-right">
<tr> <tr><td>artists:</td> <td>{{ .ArtistCount }}</td></tr>
<td>artists:</td> <td>{{ .ArtistCount }}</td> <tr><td>albums:</td> <td>{{ .AlbumCount }}</td></tr>
</tr> <tr><td>tracks:</td> <td>{{ .TrackCount }}</td></tr>
<tr>
<td>albums:</td> <td>{{ .AlbumCount }}</td>
</tr>
<tr>
<td>tracks:</td> <td>{{ .TrackCount }}</td>
</tr>
</table> </table>
</div> </div>
</div> </div>
@@ -28,13 +22,12 @@
{{ if .CurrentLastFMAPIKey }} {{ if .CurrentLastFMAPIKey }}
<span class="text-light">current status</span> <span class="text-light">current status</span>
{{ if .User.LastFMSession }} {{ if .User.LastFMSession }}
linked <span>linked</span><br/>
<span class="text-light">&#124;</span>
<form action="{{ path "/admin/unlink_lastfm_do" }}" method="post"> <form action="{{ path "/admin/unlink_lastfm_do" }}" method="post">
<input type="submit" value="unlink"> <input type="submit" value="unlink">
</form> </form>
{{ else }} {{ else }}
<span class="angry">unlinked</span> <span class="angry">unlinked</span><br/>
{{ $cbPath := path "/admin/link_lastfm_do" }} {{ $cbPath := path "/admin/link_lastfm_do" }}
{{ $cbURL := printf "%s%s" .RequestRoot $cbPath }} {{ $cbURL := printf "%s%s" .RequestRoot $cbPath }}
<a href="https://www.last.fm/api/auth/?api_key={{ .CurrentLastFMAPIKey }}&cb={{ $cbURL }}">link&#8230;</a> <a href="https://www.last.fm/api/auth/?api_key={{ .CurrentLastFMAPIKey }}&cb={{ $cbURL }}">link&#8230;</a>
@@ -52,31 +45,25 @@
</div> </div>
<div class="padded box"> <div class="padded box">
<div class="box-title"> <div class="box-title">
<i class="mdi mdi-brain"></i> ListenBrainz <i class="mdi mdi-brain"></i> listenbrainz
</div> </div>
<div class="box-description text-light"> <div class="box-description text-light">
<p>gonic can scrobble to <a href="https://listenbrainz.org/" target="_blank">ListenBrainz</a> and compatible sites.</p> <p>gonic can scrobble to <a href="https://listenbrainz.org/" target="_blank">listenbrainz</a> and compatible sites</p>
</div> </div>
<div class="text-right"> <div class="text-right">
<span class="text-light">current status</span> <span class="text-light">current status</span>
{{ if .User.ListenBrainzSession }} {{ if .User.ListenBrainzToken }}
linked <span>linked</span><br/>
<span class="text-light">&#124;</span>
<form action="{{ path "/admin/unlink_listenbrainz_do" }}" method="post"> <form action="{{ path "/admin/unlink_listenbrainz_do" }}" method="post">
<input type="submit" value="unlink"> <input type="submit" value="unlink">
</form> </form>
{{ else }} {{ else }}
<span class="angry">unlinked</span> <span class="angry">unlinked</span>
<form id="listenbrainz-pref-set" action="{{ path "/admin/link_listenbrainz_do" }}" method="post"></form> <form class="block" action="{{ path "/admin/link_listenbrainz_do" }}" method="post">
<table id="listenbrainz-pref"> <input type="text" name="url" placeholder="server addr" value="{{ default .DefaultListenBrainzURL .User.ListenBrainzURL }}">
<tr> <input type="text" name="token" placeholder="e199b311abd01f0d" value="{{ .User.ListenBrainzToken }}">
<td><label for="listenbrainz-token">Token:</label></td> <input type="submit" value="update">
<td><input form="listenbrainz-pref-set" id="listenbrainz-token" type="text" name="token" value="{{ default "" .User.ListenBrainzSession }}"></td> </form>
</tr>
<tr>
<td colspan="2"><input form="listenbrainz-pref-set" type="submit" value="save"></td>
</tr>
</table>
{{ end }} {{ end }}
</div> </div>
</div> </div>
@@ -141,7 +128,7 @@
<p class="text-light" title="{{ .LastScanTime }}">scanned {{ .LastScanTime | dateHuman }}</p> <p class="text-light" title="{{ .LastScanTime }}">scanned {{ .LastScanTime | dateHuman }}</p>
{{ end }} {{ end }}
<form action="{{ path "/admin/start_scan_inc_do" }}" method="post"> <form action="{{ path "/admin/start_scan_inc_do" }}" method="post">
<input type="submit" title="start a incremental scan" value="scan now"><br/> <input type="submit" title="start a incremental scan" value="scan now">
</form> </form>
<form action="{{ path "/admin/start_scan_full_do" }}" method="post"> <form action="{{ path "/admin/start_scan_full_do" }}" method="post">
<input type="submit" title="start a full scan (takes longer, and shouldn&#39;t usually be necessary)" value="scan full (!)"> <input type="submit" title="start a full scan (takes longer, and shouldn&#39;t usually be necessary)" value="scan full (!)">

View File

@@ -23,6 +23,7 @@ html {
font-family: monospace; font-family: monospace;
font-size: var(--size); font-size: var(--size);
color: black; color: black;
line-height: 1;
} }
body { body {
@@ -37,10 +38,12 @@ button,
textarea { textarea {
border-radius: 0; border-radius: 0;
box-sizing: border-box; box-sizing: border-box;
margin: calc(var(--size)*0.33) 0 0 0;; margin: 0;
border: 1px solid #ccc;
padding: 0; padding: 0;
vertical-align: middle; border: none;
outline: 1px solid #ccc;
height: var(--size);
vertical-align: bottom;
} }
input[type] { input[type] {
@@ -54,10 +57,6 @@ input[type="password"] {
width: 100%; width: 100%;
} }
form {
display: inline;
}
form.block { form.block {
max-width: var(--width-form); max-width: var(--width-form);
margin-left: auto; margin-left: auto;
@@ -171,8 +170,3 @@ a:hover {
.angry { .angry {
background-color: #f4433669; background-color: #f4433669;
} }
#listenbrainz-pref {
width: 100%;
margin: calc(var(--size)*0.5) 0;
}

View File

@@ -122,6 +122,7 @@ type templateData struct {
// //
CurrentLastFMAPIKey string CurrentLastFMAPIKey string
CurrentLastFMAPISecret string CurrentLastFMAPISecret string
DefaultListenBrainzURL string
SelectedUser *db.User SelectedUser *db.User
} }

View File

@@ -11,6 +11,7 @@ import (
"go.senan.xyz/gonic/server/encode" "go.senan.xyz/gonic/server/encode"
"go.senan.xyz/gonic/server/scanner" "go.senan.xyz/gonic/server/scanner"
"go.senan.xyz/gonic/server/scrobble/lastfm" "go.senan.xyz/gonic/server/scrobble/lastfm"
"go.senan.xyz/gonic/server/scrobble/listenbrainz"
) )
func firstExisting(or string, strings ...string) string { func firstExisting(or string, strings ...string) string {
@@ -58,6 +59,7 @@ func (c *Controller) ServeHome(r *http.Request) *Response {
) )
data.RequestRoot = fmt.Sprintf("%s://%s", scheme, host) data.RequestRoot = fmt.Sprintf("%s://%s", scheme, host)
data.CurrentLastFMAPIKey = c.DB.GetSetting("lastfm_api_key") data.CurrentLastFMAPIKey = c.DB.GetSetting("lastfm_api_key")
data.DefaultListenBrainzURL = listenbrainz.BaseURL
// ** begin users box // ** begin users box
c.DB.Find(&data.AllUsers) c.DB.Find(&data.AllUsers)
// ** begin recent folders box // ** begin recent folders box
@@ -163,21 +165,24 @@ func (c *Controller) ServeUnlinkLastFMDo(r *http.Request) *Response {
func (c *Controller) ServeLinkListenBrainzDo(r *http.Request) *Response { func (c *Controller) ServeLinkListenBrainzDo(r *http.Request) *Response {
token := r.FormValue("token") token := r.FormValue("token")
if token == "" { url := r.FormValue("url")
if token == "" || url == "" {
return &Response{ return &Response{
err: "please provide a token", redirect: r.Referer(),
code: 400, flashW: []string{"please provide a url and token"},
} }
} }
user := r.Context().Value(CtxUser).(*db.User) user := r.Context().Value(CtxUser).(*db.User)
user.ListenBrainzSession = token user.ListenBrainzURL = url
user.ListenBrainzToken = token
c.DB.Save(&user) c.DB.Save(&user)
return &Response{redirect: "/admin/home"} return &Response{redirect: "/admin/home"}
} }
func (c *Controller) ServeUnlinkListenBrainzDo(r *http.Request) *Response { func (c *Controller) ServeUnlinkListenBrainzDo(r *http.Request) *Response {
user := r.Context().Value(CtxUser).(*db.User) user := r.Context().Value(CtxUser).(*db.User)
user.ListenBrainzSession = "" user.ListenBrainzURL = ""
user.ListenBrainzToken = ""
c.DB.Save(&user) c.DB.Save(&user)
return &Response{redirect: "/admin/home"} return &Response{redirect: "/admin/home"}
} }

View File

@@ -55,9 +55,10 @@ func (c *Controller) ServeScrobble(r *http.Request) *spec.Response {
optSubmission := params.GetOrBool("submission", true) optSubmission := params.GetOrBool("submission", true)
scrobbleErrs := []error{} scrobbleErrs := []error{}
for _, scrobbler := range c.Scrobblers { for _, scrobbler := range c.Scrobblers {
err = scrobbler.Scrobble(user, track, optStampMili, optSubmission) if err := scrobbler.Scrobble(user, track, optStampMili, optSubmission); err != nil {
scrobbleErrs = append(scrobbleErrs, err) scrobbleErrs = append(scrobbleErrs, err)
} }
}
if len(scrobbleErrs) != 0 { if len(scrobbleErrs) != 0 {
return spec.NewError(0, "error when submitting: %v", scrobbleErrs) return spec.NewError(0, "error when submitting: %v", scrobbleErrs)
} }

View File

@@ -139,7 +139,8 @@ type User struct {
Name string `gorm:"not null; unique_index" sql:"default: null"` Name string `gorm:"not null; unique_index" sql:"default: null"`
Password string `gorm:"not null" sql:"default: null"` Password string `gorm:"not null" sql:"default: null"`
LastFMSession string `sql:"default: null"` LastFMSession string `sql:"default: null"`
ListenBrainzSession string `sql:"default: null"` ListenBrainzURL string `sql:"default: null"`
ListenBrainzToken string `sql:"default: null"`
IsAdmin bool `sql:"default: null"` IsAdmin bool `sql:"default: null"`
} }

View File

@@ -12,9 +12,9 @@ import (
) )
const ( const (
baseURL = "https://api.listenbrainz.org" BaseURL = "https://api.listenbrainz.org"
submitPath = "/1/submit-listens"
submitPath = "/1/submit-listens"
listenTypeSingle = "single" listenTypeSingle = "single"
listenTypePlayingNow = "playing_now" listenTypePlayingNow = "playing_now"
) )
@@ -47,7 +47,7 @@ type Scrobble struct {
type Scrobbler struct{} type Scrobbler struct{}
func (s *Scrobbler) Scrobble(user *db.User, track *db.Track, stampMili int, submission bool) error { func (s *Scrobbler) Scrobble(user *db.User, track *db.Track, stampMili int, submission bool) error {
if user.ListenBrainzSession == "" { if user.ListenBrainzURL == "" || user.ListenBrainzToken == "" {
return nil return nil
} }
payload := Payload{ payload := Payload{
@@ -72,9 +72,9 @@ func (s *Scrobbler) Scrobble(user *db.User, track *db.Track, stampMili int, subm
if err := json.NewEncoder(&payloadBuf).Encode(scrobble); err != nil { if err := json.NewEncoder(&payloadBuf).Encode(scrobble); err != nil {
return err return err
} }
submitURL := fmt.Sprintf("%s%s", baseURL, submitPath) submitURL := fmt.Sprintf("%s%s", user.ListenBrainzURL, submitPath)
authHeader := fmt.Sprintf("Token %s", user.ListenBrainzSession) authHeader := fmt.Sprintf("Token %s", user.ListenBrainzToken)
req, _ := http.NewRequest("POST", submitURL, &payloadBuf) req, _ := http.NewRequest(http.MethodPost, submitURL, &payloadBuf)
req.Header.Add("Authorization", authHeader) req.Header.Add("Authorization", authHeader)
res, err := http.DefaultClient.Do(req) res, err := http.DefaultClient.Do(req)
if err != nil { if err != nil {