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:
File diff suppressed because it is too large
Load Diff
@@ -5,15 +5,9 @@
|
||||
</div>
|
||||
<div class="block-right">
|
||||
<table id="stats" class="text-right">
|
||||
<tr>
|
||||
<td>artists:</td> <td>{{ .ArtistCount }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>albums:</td> <td>{{ .AlbumCount }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>tracks:</td> <td>{{ .TrackCount }}</td>
|
||||
</tr>
|
||||
<tr><td>artists:</td> <td>{{ .ArtistCount }}</td></tr>
|
||||
<tr><td>albums:</td> <td>{{ .AlbumCount }}</td></tr>
|
||||
<tr><td>tracks:</td> <td>{{ .TrackCount }}</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -28,13 +22,12 @@
|
||||
{{ if .CurrentLastFMAPIKey }}
|
||||
<span class="text-light">current status</span>
|
||||
{{ if .User.LastFMSession }}
|
||||
linked
|
||||
<span class="text-light">|</span>
|
||||
<span>linked</span><br/>
|
||||
<form action="{{ path "/admin/unlink_lastfm_do" }}" method="post">
|
||||
<input type="submit" value="unlink">
|
||||
</form>
|
||||
{{ else }}
|
||||
<span class="angry">unlinked</span>
|
||||
<span class="angry">unlinked</span><br/>
|
||||
{{ $cbPath := path "/admin/link_lastfm_do" }}
|
||||
{{ $cbURL := printf "%s%s" .RequestRoot $cbPath }}
|
||||
<a href="https://www.last.fm/api/auth/?api_key={{ .CurrentLastFMAPIKey }}&cb={{ $cbURL }}">link…</a>
|
||||
@@ -43,7 +36,7 @@
|
||||
<p class="text-light">api key not set</p>
|
||||
{{ if not .User.IsAdmin }}
|
||||
<p class="text-light">please ask your admin to set it</p>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ if .User.IsAdmin }}
|
||||
<p><a href="{{ path "/admin/update_lastfm_api_key" }}">update api key…</a></p>
|
||||
@@ -52,32 +45,26 @@
|
||||
</div>
|
||||
<div class="padded box">
|
||||
<div class="box-title">
|
||||
<i class="mdi mdi-brain"></i> ListenBrainz
|
||||
<i class="mdi mdi-brain"></i> listenbrainz
|
||||
</div>
|
||||
<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 class="text-right">
|
||||
<span class="text-light">current status</span>
|
||||
{{ if .User.ListenBrainzSession }}
|
||||
linked
|
||||
<span class="text-light">|</span>
|
||||
<form action="{{ path "/admin/unlink_listenbrainz_do" }}" method="post">
|
||||
<input type="submit" value="unlink">
|
||||
</form>
|
||||
{{ else }}
|
||||
<span class="angry">unlinked</span>
|
||||
<form id="listenbrainz-pref-set" action="{{ path "/admin/link_listenbrainz_do" }}" method="post"></form>
|
||||
<table id="listenbrainz-pref">
|
||||
<tr>
|
||||
<td><label for="listenbrainz-token">Token:</label></td>
|
||||
<td><input form="listenbrainz-pref-set" id="listenbrainz-token" type="text" name="token" value="{{ default "" .User.ListenBrainzSession }}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><input form="listenbrainz-pref-set" type="submit" value="save"></td>
|
||||
</tr>
|
||||
</table>
|
||||
{{ end }}
|
||||
<span class="text-light">current status</span>
|
||||
{{ if .User.ListenBrainzToken }}
|
||||
<span>linked</span><br/>
|
||||
<form action="{{ path "/admin/unlink_listenbrainz_do" }}" method="post">
|
||||
<input type="submit" value="unlink">
|
||||
</form>
|
||||
{{ else }}
|
||||
<span class="angry">unlinked</span>
|
||||
<form class="block" action="{{ path "/admin/link_listenbrainz_do" }}" method="post">
|
||||
<input type="text" name="url" placeholder="server addr" value="{{ default .DefaultListenBrainzURL .User.ListenBrainzURL }}">
|
||||
<input type="text" name="token" placeholder="e199b311abd01f0d" value="{{ .User.ListenBrainzToken }}">
|
||||
<input type="submit" value="update">
|
||||
</form>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="padded box">
|
||||
@@ -131,8 +118,8 @@
|
||||
</colgroup>
|
||||
{{ range $folder := .RecentFolders }}
|
||||
<tr>
|
||||
<td class="text-right text-trunc">{{ $folder.RightPath }}</td>
|
||||
<td><span class="text-light" title="{{ $folder.ModifiedAt }}">{{ $folder.ModifiedAt | dateHuman }}</span></td>
|
||||
<td class="text-right text-trunc">{{ $folder.RightPath }}</td>
|
||||
<td><span class="text-light" title="{{ $folder.ModifiedAt }}">{{ $folder.ModifiedAt | dateHuman }}</span></td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</table>
|
||||
@@ -141,7 +128,7 @@
|
||||
<p class="text-light" title="{{ .LastScanTime }}">scanned {{ .LastScanTime | dateHuman }}</p>
|
||||
{{ end }}
|
||||
<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 action="{{ path "/admin/start_scan_full_do" }}" method="post">
|
||||
<input type="submit" title="start a full scan (takes longer, and shouldn't usually be necessary)" value="scan full (!)">
|
||||
@@ -192,11 +179,11 @@
|
||||
<table id="recent-playlists">
|
||||
{{ range $i, $playlist := .Playlists }}
|
||||
<tr>
|
||||
<form id="recent-playlists-{{ $i }}" action="{{ printf "/admin/delete_playlist_do?id=%d" $playlist.ID | path }}" method="post"></form>
|
||||
<td class="text-right">{{ $playlist.Name }}</td>
|
||||
<td><span class="text-light">({{ $playlist.TrackCount }} tracks)</span></td>
|
||||
<td class="no-small"><span class="text-light" title="{{ $playlist.CreatedAt }}">{{ $playlist.CreatedAt | dateHuman }}</span></td>
|
||||
<td><input form="recent-playlists-{{ $i }}" type="submit" value="delete"></td>
|
||||
<form id="recent-playlists-{{ $i }}" action="{{ printf "/admin/delete_playlist_do?id=%d" $playlist.ID | path }}" method="post"></form>
|
||||
<td class="text-right">{{ $playlist.Name }}</td>
|
||||
<td><span class="text-light">({{ $playlist.TrackCount }} tracks)</span></td>
|
||||
<td class="no-small"><span class="text-light" title="{{ $playlist.CreatedAt }}">{{ $playlist.CreatedAt | dateHuman }}</span></td>
|
||||
<td><input form="recent-playlists-{{ $i }}" type="submit" value="delete"></td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</table>
|
||||
|
||||
@@ -23,6 +23,7 @@ html {
|
||||
font-family: monospace;
|
||||
font-size: var(--size);
|
||||
color: black;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -37,10 +38,12 @@ button,
|
||||
textarea {
|
||||
border-radius: 0;
|
||||
box-sizing: border-box;
|
||||
margin: calc(var(--size)*0.33) 0 0 0;;
|
||||
border: 1px solid #ccc;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
border: none;
|
||||
outline: 1px solid #ccc;
|
||||
height: var(--size);
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
input[type] {
|
||||
@@ -54,10 +57,6 @@ input[type="password"] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
form {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
form.block {
|
||||
max-width: var(--width-form);
|
||||
margin-left: auto;
|
||||
@@ -171,8 +170,3 @@ a:hover {
|
||||
.angry {
|
||||
background-color: #f4433669;
|
||||
}
|
||||
|
||||
#listenbrainz-pref {
|
||||
width: 100%;
|
||||
margin: calc(var(--size)*0.5) 0;
|
||||
}
|
||||
|
||||
@@ -122,6 +122,7 @@ type templateData struct {
|
||||
//
|
||||
CurrentLastFMAPIKey string
|
||||
CurrentLastFMAPISecret string
|
||||
DefaultListenBrainzURL string
|
||||
SelectedUser *db.User
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"go.senan.xyz/gonic/server/encode"
|
||||
"go.senan.xyz/gonic/server/scanner"
|
||||
"go.senan.xyz/gonic/server/scrobble/lastfm"
|
||||
"go.senan.xyz/gonic/server/scrobble/listenbrainz"
|
||||
)
|
||||
|
||||
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.CurrentLastFMAPIKey = c.DB.GetSetting("lastfm_api_key")
|
||||
data.DefaultListenBrainzURL = listenbrainz.BaseURL
|
||||
// ** begin users box
|
||||
c.DB.Find(&data.AllUsers)
|
||||
// ** begin recent folders box
|
||||
@@ -163,21 +165,24 @@ func (c *Controller) ServeUnlinkLastFMDo(r *http.Request) *Response {
|
||||
|
||||
func (c *Controller) ServeLinkListenBrainzDo(r *http.Request) *Response {
|
||||
token := r.FormValue("token")
|
||||
if token == "" {
|
||||
url := r.FormValue("url")
|
||||
if token == "" || url == "" {
|
||||
return &Response{
|
||||
err: "please provide a token",
|
||||
code: 400,
|
||||
redirect: r.Referer(),
|
||||
flashW: []string{"please provide a url and token"},
|
||||
}
|
||||
}
|
||||
user := r.Context().Value(CtxUser).(*db.User)
|
||||
user.ListenBrainzSession = token
|
||||
user.ListenBrainzURL = url
|
||||
user.ListenBrainzToken = token
|
||||
c.DB.Save(&user)
|
||||
return &Response{redirect: "/admin/home"}
|
||||
}
|
||||
|
||||
func (c *Controller) ServeUnlinkListenBrainzDo(r *http.Request) *Response {
|
||||
user := r.Context().Value(CtxUser).(*db.User)
|
||||
user.ListenBrainzSession = ""
|
||||
user.ListenBrainzURL = ""
|
||||
user.ListenBrainzToken = ""
|
||||
c.DB.Save(&user)
|
||||
return &Response{redirect: "/admin/home"}
|
||||
}
|
||||
|
||||
@@ -55,8 +55,9 @@ func (c *Controller) ServeScrobble(r *http.Request) *spec.Response {
|
||||
optSubmission := params.GetOrBool("submission", true)
|
||||
scrobbleErrs := []error{}
|
||||
for _, scrobbler := range c.Scrobblers {
|
||||
err = scrobbler.Scrobble(user, track, optStampMili, optSubmission)
|
||||
scrobbleErrs = append(scrobbleErrs, err)
|
||||
if err := scrobbler.Scrobble(user, track, optStampMili, optSubmission); err != nil {
|
||||
scrobbleErrs = append(scrobbleErrs, err)
|
||||
}
|
||||
}
|
||||
if len(scrobbleErrs) != 0 {
|
||||
return spec.NewError(0, "error when submitting: %v", scrobbleErrs)
|
||||
|
||||
@@ -134,13 +134,14 @@ func (t *Track) GenreStrings() []string {
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID int `gorm:"primary_key"`
|
||||
CreatedAt time.Time
|
||||
Name string `gorm:"not null; unique_index" sql:"default: null"`
|
||||
Password string `gorm:"not null" sql:"default: null"`
|
||||
LastFMSession string `sql:"default: null"`
|
||||
ListenBrainzSession string `sql:"default: null"`
|
||||
IsAdmin bool `sql:"default: null"`
|
||||
ID int `gorm:"primary_key"`
|
||||
CreatedAt time.Time
|
||||
Name string `gorm:"not null; unique_index" sql:"default: null"`
|
||||
Password string `gorm:"not null" sql:"default: null"`
|
||||
LastFMSession string `sql:"default: null"`
|
||||
ListenBrainzURL string `sql:"default: null"`
|
||||
ListenBrainzToken string `sql:"default: null"`
|
||||
IsAdmin bool `sql:"default: null"`
|
||||
}
|
||||
|
||||
type Setting struct {
|
||||
|
||||
@@ -12,9 +12,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
baseURL = "https://api.listenbrainz.org"
|
||||
submitPath = "/1/submit-listens"
|
||||
BaseURL = "https://api.listenbrainz.org"
|
||||
|
||||
submitPath = "/1/submit-listens"
|
||||
listenTypeSingle = "single"
|
||||
listenTypePlayingNow = "playing_now"
|
||||
)
|
||||
@@ -47,7 +47,7 @@ type Scrobble struct {
|
||||
type Scrobbler struct{}
|
||||
|
||||
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
|
||||
}
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
submitURL := fmt.Sprintf("%s%s", baseURL, submitPath)
|
||||
authHeader := fmt.Sprintf("Token %s", user.ListenBrainzSession)
|
||||
req, _ := http.NewRequest("POST", submitURL, &payloadBuf)
|
||||
submitURL := fmt.Sprintf("%s%s", user.ListenBrainzURL, submitPath)
|
||||
authHeader := fmt.Sprintf("Token %s", user.ListenBrainzToken)
|
||||
req, _ := http.NewRequest(http.MethodPost, submitURL, &payloadBuf)
|
||||
req.Header.Add("Authorization", authHeader)
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user