Add better logging and a debug mode.

This commit is contained in:
2026-01-27 09:51:54 +10:30
parent f1a57e5f85
commit ca8c26e054
3 changed files with 34 additions and 23 deletions

View File

@@ -9,6 +9,7 @@ services:
- PB_LISTENBRAINZ_USER_TOKEN=token - PB_LISTENBRAINZ_USER_TOKEN=token
- PB_PLEX_USERNAME=someusernamehere - PB_PLEX_USERNAME=someusernamehere
- PB_PLEX_LIBRARIES=Music - PB_PLEX_LIBRARIES=Music
- PB_DEBUG=false
ports: ports:
- 9102:9102 - 9102:9102
restart: unless-stopped restart: unless-stopped

54
main.go
View File

@@ -5,9 +5,10 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"log" "log/slog"
"net/http" "net/http"
"os" "os"
"strconv"
"strings" "strings"
"time" "time"
) )
@@ -22,17 +23,25 @@ func main() {
lbToken = os.Getenv("PB_LISTENBRAINZ_USER_TOKEN") lbToken = os.Getenv("PB_LISTENBRAINZ_USER_TOKEN")
plexUsername = os.Getenv("PB_PLEX_USERNAME") plexUsername = os.Getenv("PB_PLEX_USERNAME")
plexLibsStr = os.Getenv("PB_PLEX_LIBRARIES") plexLibsStr = os.Getenv("PB_PLEX_LIBRARIES")
debug, _ := strconv.ParseBool(os.Getenv("PB_DEBUG"))
if lbToken == "" { if lbToken == "" {
log.Fatal("you must set PB_LISTENBRAINZ_USER_TOKEN - see https://listenbrainz.org/settings/") slog.Error("you must set PB_LISTENBRAINZ_USER_TOKEN - see https://listenbrainz.org/settings/")
os.Exit(1)
} }
if plexUsername == "" { if plexUsername == "" {
log.Fatal("you must set PB_PLEX_USERNAME to the user who's listens will be recorded") slog.Error("you must set PB_PLEX_USERNAME to the user who's listens will be recorded")
os.Exit(1)
} }
if plexLibsStr == "" { if plexLibsStr == "" {
log.Fatal("you must set PB_PLEX_LIBRARIES to a comma separated list of plex libraries which will be scrobbled") slog.Error("you must set PB_PLEX_LIBRARIES to a comma separated list of plex libraries which will be scrobbled")
os.Exit(1)
}
if debug {
slog.SetLogLoggerLevel(slog.LevelDebug)
} }
plexLibs := strings.Split(plexLibsStr, ",") plexLibs := strings.Split(plexLibsStr, ",")
@@ -40,7 +49,7 @@ func main() {
http.HandleFunc("POST /plex", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("POST /plex", func(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(1 * 1024 * 1024) err := r.ParseMultipartForm(1 * 1024 * 1024)
if err != nil { if err != nil {
log.Printf("error parsing multipart form: %s", err.Error()) slog.Error("error parsing multipart form", "error", err.Error())
return return
} }
@@ -49,18 +58,18 @@ func main() {
err = json.Unmarshal([]byte(pl), &event) err = json.Unmarshal([]byte(pl), &event)
if err != nil { if err != nil {
log.Printf("error parsing JSON: %s", err.Error()) slog.Error("error parsing JSON", "error", err.Error())
w.WriteHeader(400) w.WriteHeader(400)
w.Write([]byte("could not parse your JSON")) w.Write([]byte("could not parse your JSON"))
return return
} }
// log.Printf("event: %s", event.Event) slog.Debug("received event", "event", event)
// log.Printf("account name: %s", event.Account.Title) // slog.Printf("account name: %s", event.Account.Title)
// log.Printf("title: %s", event.Metadata.Title) // slog.Printf("title: %s", event.Metadata.Title)
// log.Printf("album: %s", event.Metadata.ParentTitle) // slog.Printf("album: %s", event.Metadata.ParentTitle)
// log.Printf("artist: %s", event.Metadata.GrandparentTitle) // slog.Printf("artist: %s", event.Metadata.GrandparentTitle)
// log.Printf("library: %s", event.Metadata.LibrarySectionTitle) // slog.Printf("library: %s", event.Metadata.LibrarySectionTitle)
// 2025/10/19 09:21:31 event: media.play // 2025/10/19 09:21:31 event: media.play
// 2025/10/19 09:21:31 account name: username // 2025/10/19 09:21:31 account name: username
@@ -69,7 +78,7 @@ func main() {
// 2025/10/19 09:21:31 artist: Daft Punk // 2025/10/19 09:21:31 artist: Daft Punk
// 2025/10/19 09:21:31 library: Music // 2025/10/19 09:21:31 library: Music
if event.Account.Title != plexUsername { if event.Account.Title != plexUsername {
log.Printf("not scrobbling for user '%s'", plexUsername) slog.Error("not scrobbling for this user", "user", event.Account.Title)
w.WriteHeader(200) w.WriteHeader(200)
w.Write([]byte("ok")) w.Write([]byte("ok"))
return return
@@ -84,8 +93,8 @@ func main() {
} }
} }
if !found { if !found {
log.Printf("not scrobbling for library '%s'", event.Metadata.LibrarySectionTitle) slog.Debug("not scrobbling for this library", "library", event.Metadata.LibrarySectionTitle)
log.Printf("does not match one of: '%s'", plexLibsStr) slog.Debug("does not match a configured library", "libraries", plexLibsStr)
w.WriteHeader(200) w.WriteHeader(200)
w.Write([]byte("ok")) w.Write([]byte("ok"))
return return
@@ -93,26 +102,27 @@ func main() {
err = lbSubmit(event.Metadata.Title, event.Metadata.GrandparentTitle, event.Metadata.ParentTitle) err = lbSubmit(event.Metadata.Title, event.Metadata.GrandparentTitle, event.Metadata.ParentTitle)
if err != nil { if err != nil {
log.Printf("error submitting: %s", err.Error()) slog.Error("error submitting to listenbrainz", "error", err.Error())
w.WriteHeader(400) w.WriteHeader(400)
w.Write([]byte("could not parse your JSON")) w.Write([]byte("could not submit to listenbrainz"))
return return
} else { } else {
log.Printf("scrobbled play of %s - %s", event.Metadata.GrandparentTitle, event.Metadata.Title) slog.Info("scrobbled play", "grandparent", event.Metadata.GrandparentTitle, "title", event.Metadata.Title)
w.WriteHeader(200) w.WriteHeader(200)
w.Write([]byte("ok")) w.Write([]byte("ok"))
return return
} }
} else { } else {
log.Printf("non scrobble event: %s", event.Event) slog.Debug("non scrobble event", "event", event.Event)
w.WriteHeader(200) w.WriteHeader(200)
w.Write([]byte("ok")) w.Write([]byte("ok"))
return return
} }
}) })
log.Printf("starting web server on %s", listen) slog.Info("starting web server", "listen", listen)
log.Fatal(http.ListenAndServe(listen, nil)) slog.Error(http.ListenAndServe(listen, nil).Error())
os.Exit(1)
} }
func lbSubmit(title, artist, album string) error { func lbSubmit(title, artist, album string) error {
@@ -161,7 +171,7 @@ func lbSubmit(title, artist, album string) error {
// happy path // happy path
resB := bytes.Buffer{} resB := bytes.Buffer{}
io.Copy(&resB, res.Body) io.Copy(&resB, res.Body)
log.Printf("listenbrainz OK - response: `%s`", resB.String()) slog.Debug("listenbrainz OK", "response", resB.String())
return nil return nil
} }

View File

@@ -66,7 +66,7 @@ type webhookEvent struct {
Filter string `json:"filter"` Filter string `json:"filter"`
Tag string `json:"tag"` Tag string `json:"tag"`
} `json:"Genre"` } `json:"Genre"`
GUID0 []struct { OtherGUID []struct {
ID string `json:"id"` ID string `json:"id"`
} `json:"Guid"` } `json:"Guid"`
Mood []struct { Mood []struct {