From 56eae672922ae7489cc607f18a953de2b3bfb4df Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 21 Nov 2023 18:39:15 +0100 Subject: [PATCH] scrobblerlog: implemented append mode --- backends/scrobblerlog/parser.go | 4 +- backends/scrobblerlog/parser_test.go | 12 ++++++ backends/scrobblerlog/scrobblerlog.go | 53 ++++++++++++++++++++++----- scotty.example.toml | 3 ++ 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/backends/scrobblerlog/parser.go b/backends/scrobblerlog/parser.go index ccda522..aeb0305 100644 --- a/backends/scrobblerlog/parser.go +++ b/backends/scrobblerlog/parser.go @@ -46,7 +46,7 @@ func Parse(data io.Reader, includeSkipped bool) (ScrobblerLog, error) { } reader := bufio.NewReader(data) - err := readHeader(reader, &result) + err := ReadHeader(reader, &result) if err != nil { return result, err } @@ -123,7 +123,7 @@ func Write(data io.Writer, listens models.ListensList) (lastTimestamp time.Time, return } -func readHeader(reader *bufio.Reader, log *ScrobblerLog) error { +func ReadHeader(reader *bufio.Reader, log *ScrobblerLog) error { // Skip header for i := 0; i < 3; i++ { line, _, err := reader.ReadLine() diff --git a/backends/scrobblerlog/parser_test.go b/backends/scrobblerlog/parser_test.go index af6af09..8b32724 100644 --- a/backends/scrobblerlog/parser_test.go +++ b/backends/scrobblerlog/parser_test.go @@ -22,6 +22,7 @@ THE SOFTWARE. package scrobblerlog_test import ( + "bufio" "bytes" "strings" "testing" @@ -114,3 +115,14 @@ func TestWrite(t *testing.T) { assert.Equal("", lines[4]) assert.Equal(time.Unix(1699572072, 0), lastTimestamp) } + +func TestReadHeader(t *testing.T) { + data := bytes.NewBufferString(testScrobblerLog) + reader := bufio.NewReader(data) + log := scrobblerlog.ScrobblerLog{} + err := scrobblerlog.ReadHeader(reader, &log) + assert.NoError(t, err) + assert.Equal(t, log.Timezone, "UNKNOWN") + assert.Equal(t, log.Client, "Rockbox sansaclipplus $Revision$") + assert.Empty(t, log.Listens) +} diff --git a/backends/scrobblerlog/scrobblerlog.go b/backends/scrobblerlog/scrobblerlog.go index e373e0b..47b445a 100644 --- a/backends/scrobblerlog/scrobblerlog.go +++ b/backends/scrobblerlog/scrobblerlog.go @@ -22,6 +22,7 @@ THE SOFTWARE. package scrobblerlog import ( + "bufio" "os" "sort" "time" @@ -33,6 +34,7 @@ import ( type ScrobblerLogBackend struct { filePath string includeSkipped bool + append bool file *os.File log ScrobblerLog } @@ -42,26 +44,57 @@ func (b *ScrobblerLogBackend) Name() string { return "scrobbler-log" } func (b *ScrobblerLogBackend) FromConfig(config *viper.Viper) models.Backend { b.filePath = config.GetString("file-path") b.includeSkipped = config.GetBool("include-skipped") - return b -} - -func (b *ScrobblerLogBackend) StartImport() error { - file, err := os.Create(b.filePath) - if err != nil { - return err + b.append = true + if config.IsSet("append") { + b.append = config.GetBool("append") } - b.log = ScrobblerLog{ Timezone: "UNKNOWN", Client: "Rockbox unknown $Revision$", } + return b +} - err = WriteHeader(file, &b.log) +func (b *ScrobblerLogBackend) StartImport() error { + flags := os.O_RDWR | os.O_CREATE + if !b.append { + flags |= os.O_TRUNC + } + file, err := os.OpenFile(b.filePath, flags, 0666) if err != nil { - file.Close() return err } + if b.append { + stat, err := file.Stat() + if err != nil { + file.Close() + return err + } + + if stat.Size() == 0 { + // Zero length file, treat as a new file + b.append = false + } else { + // Verify existing file is a scrobbler log + reader := bufio.NewReader(file) + err = ReadHeader(reader, &b.log) + if err != nil { + file.Close() + return err + } + file.Seek(0, 2) + } + } + + if !b.append { + err = WriteHeader(file, &b.log) + if err != nil { + file.Close() + return err + } + } + b.file = file return nil } diff --git a/scotty.example.toml b/scotty.example.toml index 54aad0d..e358bb5 100644 --- a/scotty.example.toml +++ b/scotty.example.toml @@ -50,6 +50,9 @@ backend = "scrobbler-log" file-path = "data/.scrobbler.log" # If true, reading listens from the file also returns listens marked as "skipped" include-skipped = true +# If true (default), new listens will be appended to the existing file. Set to +# false to overwrite the file and create a new scrobbler log on every run. +append = true [service.jspf] # Write listens and loves to JSPF playlist files (https://xspf.org/jspf)