diff --git a/internal/infra/m3u.go b/internal/infra/m3u.go new file mode 100644 index 0000000..2b98f9d --- /dev/null +++ b/internal/infra/m3u.go @@ -0,0 +1,29 @@ +package infra + +import ( + "fmt" + "strings" + + "radio-go/internal/domain" +) + +// sanitize flattens a string so it can't break or forge an m3u line: +// newlines become spaces and "#EXT" sequences are stripped so a song title +// can never inject a fake #EXTINF entry. +func sanitize(s string) string { + return strings.ReplaceAll( + strings.NewReplacer("\r", " ", "\n", " ").Replace(s), + "#EXT", "") +} + +// WriteM3U renders an extended M3U playlist (relative mp3 names). +func WriteM3U(station string, pl []domain.Track) string { + var b strings.Builder + b.WriteString("#EXTM3U\n") + for _, t := range pl { + dur := int(t.Duration) + title := sanitize(fmt.Sprintf("%s - %s", station, t.DisplayTitle())) + fmt.Fprintf(&b, "#EXTINF:%d,%s\n%s.mp3\n", dur, title, t.ID) + } + return b.String() +}