mcg/internal/common/album.go
2026-08-14 11:54:59 +02:00

189 lines
3.3 KiB
Go

package common
import (
"crypto/md5"
"fmt"
"io"
"path/filepath"
"slices"
"strings"
"time"
"suruatoel.xyz/mcg/internal/i18n"
)
type Album struct {
title string
songs []*Song
artists []string
pathes []string
dates []string
length uint64
lastModified time.Time
}
func NewAlbum(title string) *Album {
album := Album{
title: title,
}
return &album
}
func (a *Album) Title() string {
return a.title
}
func (a *Album) AddSong(song *Song) {
a.songs = append(a.songs, song)
a.length += song.Length()
for _, artist := range song.AlbumArtists() {
if !slices.Contains(a.artists, artist) {
a.artists = append(a.artists, artist)
}
}
if !slices.Contains(a.dates, song.Date()) {
a.dates = append(a.dates, song.Date())
}
path := filepath.Base(song.File())
if !slices.Contains(a.pathes, path) {
a.pathes = append(a.pathes, path)
}
if !song.LastModified().After(a.lastModified) {
a.lastModified = song.LastModified()
}
}
func (a *Album) Songs() []*Song {
return a.songs
}
func (a *Album) Artists() []string {
return a.artists
}
func (a *Album) Dates() []string {
return a.dates
}
func (a *Album) Length() uint64 {
return a.length
}
func (a *Album) LastModified() time.Time {
return a.lastModified
}
func (a *Album) ID() string {
return generateAlbumId(a.title)
}
func (a *Album) Tooltip() string {
artists := strings.Join(a.Artists(), ", ")
dates := strings.Join(a.dates, ", ")
minutes := a.length / 60
seconds := a.length - minutes*60
length := fmt.Sprintf(i18n.T("%d:%d minutes"), minutes, seconds)
return strings.Join(
[]string{
a.title,
dates,
artists,
length,
},
"\n",
)
}
type PlaylistAlbum struct {
*Album
songs []*PlaylistSong
length uint64
}
func NewPlaylistAlbum(album *Album) *PlaylistAlbum {
playlistAlbum := PlaylistAlbum{
Album: album,
}
return &playlistAlbum
}
func (a *PlaylistAlbum) AddSong(playlistSong *PlaylistSong) {
a.songs = append(a.songs, playlistSong)
song := playlistSong.Song
a.length += song.Length()
for _, artist := range song.AlbumArtists() {
if !slices.Contains(a.artists, artist) {
a.artists = append(a.artists, artist)
}
}
if !slices.Contains(a.dates, song.Date()) {
a.dates = append(a.dates, song.Date())
}
path := filepath.Base(song.File())
if !slices.Contains(a.pathes, path) {
a.pathes = append(a.pathes, path)
}
}
func (a *PlaylistAlbum) Songs() []*PlaylistSong {
return a.songs
}
func (a *PlaylistAlbum) Length() uint64 {
return a.length
}
func (a *Album) IsMatch(query string) bool {
if query == "" {
return true
}
for keyword := range strings.SplitSeq(query, " ") {
if !a.isKeywordMatch(keyword) {
return false
}
}
return true
}
func (a *Album) isKeywordMatch(keyword string) bool {
if strings.Contains(strings.ToLower(a.title), keyword) {
return true
}
for _, artist := range a.artists {
if strings.Contains(strings.ToLower(artist), keyword) {
return true
}
}
for _, song := range a.songs {
if strings.Contains(strings.ToLower(song.Title()), keyword) {
return true
}
if strings.Contains(strings.ToLower(song.File()), keyword) {
return true
}
}
return false
}
func generateAlbumId(values ...string) string {
h := md5.New()
for _, value := range values {
io.WriteString(h, value)
}
return fmt.Sprintf("%x", h.Sum(nil))
}