package main import ( "fmt" "io" "log" "os" "path/filepath" "strings" "github.com/bogem/id3v2/v2" "github.com/go-flac/flacpicture" "github.com/go-flac/go-flac" ) // has func hasFlacTrackArt(s string) bool { // dumb check if !strings.HasSuffix(s, ".flac") { return false } // is parsable f, err := flac.ParseFile(s) if err != nil { return false } // has any frames if len(f.Meta) == 0 { return false } // has any pictures for _, metadata := range f.Meta { if metadata.Type == flac.Picture { return true } } // no pictures return false } func hasMp3TrackArt(s string) bool { // dumb check if !strings.HasSuffix(s, ".mp3") { return false } // is parsable m, err := id3v2.Open(s, id3v2.Options{Parse: true}) if err != nil { return false } defer m.Close() // has a picture pic := m.GetFrames(m.CommonID("Attached picture")) if pic != nil { return true } // no pictures return false } func hasCoverArtFile(s string) bool { exts := []string{".jpg", ".jpeg", ".png", ".gif"} // check all sane image types dir := filepath.Dir(s) file, err := os.Open(dir) if err != nil { log.Printf("can't open %v; %v\n", dir, err.Error()) return false } defer file.Close() indexes, _ := file.ReadDir(0) for i := range indexes { for _, key := range exts { if "cover"+key == indexes[i].Name() { return true } } } return false } // get func getFlacArt(s string) ([]byte, error) { f, err := flac.ParseFile(s) if err != nil { return nil, fmt.Errorf("can't open file") } for _, metadata := range f.Meta { if metadata.Type == flac.Picture { // do not care if it has multiple pictures, pick the first one. pic, err := flacpicture.ParseFromMetaDataBlock(*metadata) return pic.ImageData, err } } return nil, fmt.Errorf("no image found") } func getMP3Art(s string) ([]byte, error) { tags, err := id3v2.Open(s, id3v2.Options{Parse: true}) if err != nil { return nil, fmt.Errorf("can't open mp3 tags") } defer tags.Close() pic := tags.GetFrames(tags.CommonID("Attached picture")) if pic != nil { // do not care if it has multiple pictures, pick the first one. return pic[0].(id3v2.PictureFrame).Picture, nil } return nil, fmt.Errorf("no image found") } func getCoverArtFile(s string) ([]byte, error) { exts := []string{".jpg", ".jpeg", ".png", ".gif"} dir := filepath.Dir(s) file, err := os.Open(dir) if err != nil { return nil, fmt.Errorf("can't open %v; %v", dir, err.Error()) } defer file.Close() indexes, _ := file.ReadDir(0) for i := range indexes { for _, key := range exts { if "cover"+key == indexes[i].Name() { cover, err := os.Open(dir + "/" + indexes[i].Name()) if err != nil { return nil, fmt.Errorf("can't open %v", indexes[i].Name()) } defer cover.Close() if err != nil { return nil, fmt.Errorf("cant stat %v; %v", indexes[i].Name(), err.Error()) } return io.ReadAll(cover) } } } return nil, fmt.Errorf("cover not found") } func getDefaultArt() ([]byte, error) { file, err := os.Open("default.jpg") if err != nil { return []byte{}, err } defer file.Close() info, err := file.Stat() if err != nil { return []byte{}, err } art := make([]byte, info.Size()) file.Read(art) return art, err }