From dc4d9e4e96c905f6edcfcdddae0a16214b3b054d Mon Sep 17 00:00:00 2001 From: sentriz Date: Thu, 21 Apr 2022 01:30:33 +0100 Subject: [PATCH] feat(subsonic): add detailed logging about requested audio closes #212 --- server/ctrlsubsonic/handlers_raw.go | 65 +++++++++++++---------------- 1 file changed, 29 insertions(+), 36 deletions(-) diff --git a/server/ctrlsubsonic/handlers_raw.go b/server/ctrlsubsonic/handlers_raw.go index d60243ce..c79be8c2 100644 --- a/server/ctrlsubsonic/handlers_raw.go +++ b/server/ctrlsubsonic/handlers_raw.go @@ -42,24 +42,32 @@ func streamGetTransPref(dbc *db.DB, userID int, client string) (*db.TranscodePre return &pref, nil } -func streamGetTrack(dbc *db.DB, trackID int) (*db.Track, error) { - var track db.Track - err := dbc. - Preload("Album"). - First(&track, trackID). - Error - if err != nil { - return nil, fmt.Errorf("find track: %w", err) - } - return &track, nil -} +var errUnknownMediaType = fmt.Errorf("media type is unknown") -func streamGetPodcast(dbc *db.DB, podcastID int) (*db.PodcastEpisode, error) { - var podcast db.PodcastEpisode - if err := dbc.First(&podcast, podcastID).Error; err != nil { - return nil, fmt.Errorf("find podcast: %w", err) +// TODO: there is a mismatch between abs paths for podcasts and music. if they were the same, db.AudioFile +// could have an AbsPath() method. and we wouldn't need to pass podcastsPath or return 3 values +func streamGetAudio(dbc *db.DB, podcastsPath string, user *db.User, id specid.ID) (db.AudioFile, string, error) { + switch t := id.Type; t { + case specid.Track: + var track db.Track + if err := dbc.Preload("Album").Preload("Artist").First(&track, id.Value).Error; err != nil { + return nil, "", fmt.Errorf("find track: %w", err) + } + if track.Artist != nil && track.Album != nil { + log.Printf("%s requests %s - %s from %s", user.Name, track.Artist.Name, track.TagTitle, track.Album.TagTitle) + } + return &track, path.Join(track.AbsPath()), nil + + case specid.PodcastEpisode: + var podcast db.PodcastEpisode + if err := dbc.First(&podcast, id.Value).Error; err != nil { + return nil, "", fmt.Errorf("find podcast: %w", err) + } + return &podcast, path.Join(podcastsPath, podcast.Path), nil + + default: + return nil, "", fmt.Errorf("%w: %q", errUnknownMediaType, t) } - return &podcast, nil } func streamUpdateStats(dbc *db.DB, userID, albumID int, playTime time.Time) error { @@ -236,32 +244,17 @@ func (c *Controller) ServeGetCoverArt(w http.ResponseWriter, r *http.Request) *s func (c *Controller) ServeStream(w http.ResponseWriter, r *http.Request) *spec.Response { params := r.Context().Value(CtxParams).(params.Params) + user := r.Context().Value(CtxUser).(*db.User) id, err := params.GetID("id") if err != nil { return spec.NewError(10, "please provide an `id` parameter") } - var file db.AudioFile - var audioPath string - switch id.Type { - case specid.Track: - track, err := streamGetTrack(c.DB, id.Value) - if err != nil { - return spec.NewError(70, "track with id `%s` was not found", id) - } - file = track - audioPath = path.Join(track.AbsPath()) - case specid.PodcastEpisode: - podcast, err := streamGetPodcast(c.DB, id.Value) - if err != nil { - return spec.NewError(70, "podcast with id `%s` was not found", id) - } - file = podcast - audioPath = path.Join(c.PodcastsPath, podcast.Path) - default: - return spec.NewError(70, "media type of `%s` was not found", id.Type) + + file, audioPath, err := streamGetAudio(c.DB, c.PodcastsPath, user, id) + if err != nil { + return spec.NewError(70, "error finding media: %v", err) } - user := r.Context().Value(CtxUser).(*db.User) if track, ok := file.(*db.Track); ok && track.Album != nil { defer func() { if err := streamUpdateStats(c.DB, user.ID, track.Album.ID, time.Now()); err != nil {