lyrics

lyrics
git clone git://brookjeynes.dev/bjeynes/lyrics.git
Log | Files | Refs

commit 9ae8db3e88a3309188c71e2596c1687887fbce1d
parent 1df261605d32d2eaacd6b56b0d7d40a8a9a0d08a
Author: brookjeynes <me@brookjeynes.dev>
Date:   Sun, 14 Jun 2026 17:48:18 +1000

feat(albums): save MusicBrainz release IDs

Signed-off-by: brookjeynes <me@brookjeynes.dev>

Diffstat:
Minternal/server/edit-album.go | 31+++++++++++++++++++++----------
Minternal/server/new-album.go | 28++++++++++++++++++++--------
Minternal/server/ui/views/edit-album/edit-album.templ | 16++++++++++++++++
Minternal/server/ui/views/new-album/new-album.templ | 13+++++++++++++
4 files changed, 70 insertions(+), 18 deletions(-)

diff --git a/internal/server/edit-album.go b/internal/server/edit-album.go @@ -14,11 +14,12 @@ import ( ) type EditAlbumForm struct { - Title string `schema:"album"` - LatinTitle string `schema:"latin-title"` - ArtistID []domain.ArtistID `schema:"artist-id"` - SongID []domain.SongID `schema:"song-id"` - ReleaseDate string `schema:"release-date"` + Title string `schema:"album"` + LatinTitle string `schema:"latin-title"` + ArtistID []domain.ArtistID `schema:"artist-id"` + SongID []domain.SongID `schema:"song-id"` + ReleaseDate string `schema:"release-date"` + MusicBrainzReleaseID domain.MusicBrainzID `schema:"musicbrainz-release-id"` } func parseEditAlbumForm(form EditAlbumForm) (domain.EditAlbum, error) { @@ -95,12 +96,22 @@ func parseEditAlbumForm(form EditAlbumForm) (domain.EditAlbum, error) { }) } + // musicbrainz release id + var musicbrainzReleaseID *domain.MusicBrainzID + if form.MusicBrainzReleaseID != "" { + if !domain.MusicBrainzIDIsValid(string(form.MusicBrainzReleaseID)) { + return album, fmt.Errorf("'%s' must be a valid MusicBrainz ID", form.MusicBrainzReleaseID) + } + musicbrainzReleaseID = &form.MusicBrainzReleaseID + } + album = domain.EditAlbum{ - Title: form.Title, - LatinTitle: latinTitle, - ReleaseDate: releaseDate, - Artists: artists, - Songs: songs, + MusicBrainzReleaseID: musicbrainzReleaseID, + Title: form.Title, + LatinTitle: latinTitle, + ReleaseDate: releaseDate, + Artists: artists, + Songs: songs, } return album, nil diff --git a/internal/server/new-album.go b/internal/server/new-album.go @@ -13,10 +13,11 @@ import ( ) type NewAlbumForm struct { - Title string `schema:"album"` - LatinTitle string `schema:"latin-title"` - ArtistID []domain.ArtistID `schema:"artist-id"` - ReleaseDate string `schema:"release-date"` + Title string `schema:"album"` + LatinTitle string `schema:"latin-title"` + ArtistID []domain.ArtistID `schema:"artist-id"` + ReleaseDate string `schema:"release-date"` + MusicBrainzReleaseID domain.MusicBrainzID `schema:"musicbrainz-release-id"` } func parseNewAlbumForm(form NewAlbumForm) (domain.NewAlbum, error) { @@ -63,6 +64,7 @@ func parseNewAlbumForm(form NewAlbumForm) (domain.NewAlbum, error) { latinTitle = &form.LatinTitle } + // release date releaseDate, err := time.Parse("2006-01-02", form.ReleaseDate) if err != nil { return album, fmt.Errorf("Invalid release date: %w", err) @@ -74,11 +76,21 @@ func parseNewAlbumForm(form NewAlbumForm) (domain.NewAlbum, error) { minDate.Format("2006-01-02"), maxDate.Format("2006-01-02")) } + // musicbrainz release id + var musicbrainzReleaseID *domain.MusicBrainzID + if form.MusicBrainzReleaseID != "" { + if !domain.MusicBrainzIDIsValid(string(form.MusicBrainzReleaseID)) { + return album, fmt.Errorf("'%s' must be a valid MusicBrainz ID", form.MusicBrainzReleaseID) + } + musicbrainzReleaseID = &form.MusicBrainzReleaseID + } + album = domain.NewAlbum{ - Title: form.Title, - LatinTitle: latinTitle, - ReleaseDate: releaseDate, - Artists: artists, + MusicBrainzReleaseID: musicbrainzReleaseID, + Title: form.Title, + LatinTitle: latinTitle, + ReleaseDate: releaseDate, + Artists: artists, } return album, nil diff --git a/internal/server/ui/views/edit-album/edit-album.templ b/internal/server/ui/views/edit-album/edit-album.templ @@ -178,6 +178,22 @@ templ EditAlbum(params EditAlbumParams) { </ol> } </fieldset> + <fieldset> + <legend>MusicBrainz</legend> + <label title="External identifier used for metadata lookups such as cover art. This app does not contact MusicBrainz when saving."> + Release ID (optional): + <input + name="musicbrainz-release-id" + type="text" + if params.Album.MusicBrainzReleaseID != nil { + value={ *params.Album.MusicBrainzReleaseID } + } + pattern={ domain.IsValidMusicBrainzIDPattern } + placeholder="e32a4ae3-67d1-4541-84d8-de6ab2d7dec1" + /> + <i data-lucide="info"></i> + </label> + </fieldset> <footer aria-label="Form actions"> <button class="-primary" id="save-album-btn" type="submit">save changes</button> <a href={ routes.Album(params.Album) }>cancel</a> diff --git a/internal/server/ui/views/new-album/new-album.templ b/internal/server/ui/views/new-album/new-album.templ @@ -128,6 +128,19 @@ templ NewAlbum(params NewAlbumParams) { /> </label> </fieldset> + <fieldset> + <legend>MusicBrainz</legend> + <label title="External identifier used for metadata lookups such as cover art. This app does not contact MusicBrainz when saving."> + Release ID (optional): + <input + name="musicbrainz-release-id" + type="text" + pattern={ domain.IsValidMusicBrainzIDPattern } + placeholder="e32a4ae3-67d1-4541-84d8-de6ab2d7dec1" + /> + <i data-lucide="info"></i> + </label> + </fieldset> <footer aria-label="Form actions"> <button class="-primary" id="add-album-btn" type="submit">add album</button> </footer>