Rockbox scrobbler.log listen reader

This commit is contained in:
Philipp Wolfer 2023-11-09 16:41:27 +01:00
parent 8661075975
commit 0b3b3b768d
No known key found for this signature in database
GPG key ID: 8FDF744D4919943B

View file

@ -22,6 +22,14 @@ THE SOFTWARE.
package backends
import (
"bufio"
"encoding/csv"
"errors"
"fmt"
"io"
"os"
"strconv"
"strings"
"time"
"github.com/spf13/viper"
@ -39,5 +47,124 @@ func (b ScrobblerLogBackend) FromConfig(config *viper.Viper) Backend {
}
func (b ScrobblerLogBackend) ExportListens(oldestTimestamp time.Time) ([]Listen, error) {
return nil, nil
file, err := os.Open(b.filePath)
if err != nil {
return nil, err
}
defer file.Close()
reader := bufio.NewReader(file)
client, err := readHeader(reader)
if err != nil {
return nil, err
}
csvReader := csv.NewReader(reader)
csvReader.Comma = '\t'
// Row length is often flexible
csvReader.FieldsPerRecord = -1
listens := make([]Listen, 0)
for {
// A row is:
// artistName releaseName trackName trackNumber duration rating timestamp recordingMbid
row, err := csvReader.Read()
if err == io.EOF {
break
} else if err != nil {
return nil, err
}
// fmt.Printf("row: %v\n", row)
// We consider only the last field (recording MBID) optional
if len(row) < 7 {
line, _ := csvReader.FieldPos(0)
return nil, errors.New(fmt.Sprintf(
"Invalid record in %s line %v", b.filePath, line))
}
rating := row[5]
if !b.includeSkipped && rating == "S" {
continue
}
listen, err := rowToListen(row, client)
if err != nil {
return nil, err
}
listens = append(listens, listen)
}
return listens, nil
}
func readHeader(reader *bufio.Reader) (client string, err error) {
// Skip header
for i := 0; i < 3; i++ {
line, _, err := reader.ReadLine()
if err != nil {
return client, err
}
if len(line) == 0 || line[0] != '#' {
err = errors.New(fmt.Sprintf("Unexpected header (line %v)", i))
} else {
text := string(line)
if i == 0 && !strings.HasPrefix(text, "#AUDIOSCROBBLER/1") {
err = errors.New(fmt.Sprintf("Not a scrobbler log file"))
}
after, found := strings.CutPrefix(text, "#CLIENT/")
if found {
client = strings.Split(after, " ")[0]
}
}
if err != nil {
return client, err
}
}
return client, nil
}
func rowToListen(row []string, client string) (Listen, error) {
var listen Listen
trackNumber, err := strconv.Atoi(row[3])
if err != nil {
return listen, err
}
duration, err := strconv.Atoi(row[4])
if err != nil {
return listen, err
}
timestamp, err := strconv.Atoi(row[6])
if err != nil {
return listen, err
}
listen = Listen{
Track: Track{
ArtistNames: []string{row[0]},
ReleaseName: row[1],
TrackName: row[2],
TrackNumber: trackNumber,
Duration: time.Duration(duration),
AdditionalInfo: AdditionalInfo{
"rockbox_rating": row[5],
"media_player": client,
},
},
ListenedAt: time.Unix(int64(timestamp), 0),
}
if len(row) > 7 {
listen.Track.RecordingMbid = MBID(row[7])
}
return listen, nil
}