playlist phantom track matching added, updated search queries for efficiency

This commit is contained in:
2026-02-24 21:23:25 -05:00
parent ff7649600b
commit e192d4625e
31 changed files with 5222 additions and 316 deletions
+81 -9
View File
@@ -19,7 +19,6 @@ const (
)
var (
errInvalidM3U = errors.New("invalid M3U file: missing #EXTM3U header")
errEmptyM3UFile = errors.New("M3U file is empty")
errPlaylistDirNil = errors.New("playlists directory path is empty")
)
@@ -132,15 +131,15 @@ func parseM3U8(filePath string) (parsedPlaylist, error) {
continue
}
// Check header.
// Check header. If the first non-empty line is not
// #EXTM3U, treat the file as a simple M3U (just
// path lines) and fall through to process normally.
if !headerSeen {
if line == m3uHeader {
headerSeen = true
headerSeen = true
if line == m3uHeader {
continue
}
return parsedPlaylist{}, errInvalidM3U
}
// Playlist name directive.
@@ -300,11 +299,16 @@ func findPlaylistFile(
)
}
if len(matches) == 0 {
return "", nil
// Filter matches to ensure the extracted ID matches the
// target. The glob pattern "1-*.m3u8" also matches
// "10-foo.m3u8", "11-bar.m3u8", etc.
for _, m := range matches {
if extractPlaylistID(m) == id {
return m, nil
}
}
return matches[0], nil
return "", nil
}
// removeOldPlaylistFile removes an old playlist file for the given
@@ -409,6 +413,74 @@ func extractPlaylistID(filePath string) int64 {
return id
}
// removeM3UEntries removes entries from a slice whose resolved
// absolute paths appear in the target set.
func removeM3UEntries(
entries []m3uEntry,
targetAbsPaths map[string]struct{},
libraryRoot string,
) []m3uEntry {
result := make([]m3uEntry, 0, len(entries))
for _, e := range entries {
absPath := toAbsolutePath(
e.RelativePath, libraryRoot,
)
if _, remove := targetAbsPaths[absPath]; remove {
continue
}
result = append(result, e)
}
return result
}
// replaceM3UEntryPaths replaces the relative paths of entries
// whose resolved absolute paths match keys in the replacements
// map. Values are new relative paths.
func replaceM3UEntryPaths(
entries []m3uEntry,
replacements map[string]string,
libraryRoot string,
) []m3uEntry {
result := make([]m3uEntry, len(entries))
for i, e := range entries {
result[i] = e
absPath := toAbsolutePath(
e.RelativePath, libraryRoot,
)
if newRel, ok := replacements[absPath]; ok {
result[i].RelativePath = newRel
}
}
return result
}
// findM3UEntry finds the M3U entry whose resolved absolute path
// matches the given target path. Returns the entry and its index,
// or -1 if not found.
func findM3UEntry(
entries []m3uEntry,
targetAbsPath string,
libraryRoot string,
) (m3uEntry, int) {
for i, e := range entries {
absPath := toAbsolutePath(
e.RelativePath, libraryRoot,
)
if absPath == targetAbsPath {
return e, i
}
}
return m3uEntry{}, -1
}
// displayTitle builds an EXTINF display title from artist and title.
func displayTitle(artist, title string) string {
artist = strings.TrimSpace(artist)