diff options
| author | Franck Cuny <franck@fcuny.net> | 2025-08-29 09:23:18 -0700 |
|---|---|---|
| committer | Franck Cuny <franck@fcuny.net> | 2025-08-29 09:23:18 -0700 |
| commit | 91ead5e4493bb459ea537ad204e7e6b3d15a220b (patch) | |
| tree | f712f9d75a969479bda177bc439918ed2a1008f0 /internal/scrobbler/scrobbler.go | |
| parent | fix readme for x509-info project (diff) | |
| parent | prepare the migration (diff) | |
| download | x-91ead5e4493bb459ea537ad204e7e6b3d15a220b.tar.gz | |
Merge remote-tracking branch 'import/main'
Diffstat (limited to 'internal/scrobbler/scrobbler.go')
| -rw-r--r-- | internal/scrobbler/scrobbler.go | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/internal/scrobbler/scrobbler.go b/internal/scrobbler/scrobbler.go new file mode 100644 index 0000000..f0f9d0e --- /dev/null +++ b/internal/scrobbler/scrobbler.go @@ -0,0 +1,118 @@ +package scrobbler + +import ( + "database/sql" + "log" + "time" + + "golang.fcuny.net/mpd-stats/internal/mpd" +) + +type Scrobbler struct { + player *mpd.Player + db *sql.DB +} + +func NewScrobbler(net string, addr string, dbpath string) (*Scrobbler, error) { + p, err := mpd.NewPlayer(net, addr) + if err != nil { + return nil, err + } + + db, err := opendatabase(dbpath) + if err != nil { + return nil, err + } + + s := Scrobbler{ + player: p, + db: db, + } + + return &s, nil +} + +func (s *Scrobbler) Close() error { + return s.player.Close() +} + +func (s *Scrobbler) Run() error { + var ( + currentRecord *Record + previousRecord *Record + ) + + for { + e := <-s.player.Watcher.Event + if e != "" { + status, err := s.player.Client.Status() + if err != nil { + log.Printf("could not read the status: %v", err) + } + + if status["state"] == "stop" { + if currentRecord != nil { + if err := s.update(currentRecord); err != nil { + log.Printf("failed to update record %s: %s", currentRecord.Id, err) + } + currentRecord = nil + } + continue + } + + attrs, err := s.player.Client.CurrentSong() + if err != nil { + log.Printf("could not get current song: %v", err) + } + + if currentRecord == nil { + currentRecord, err = NewRecord(attrs) + if err != nil { + log.Printf("could not create a log: %v", err) + } + previousRecord = currentRecord + if err := s.save(currentRecord); err != nil { + log.Printf("failed to insert record %s: %s", currentRecord.Id, err) + } + continue + } + + if !currentRecord.EqualAttrs(attrs) { + currentRecord, err = NewRecord(attrs) + if err != nil { + log.Printf("could not create a log: %v", err) + } + } + + if currentRecord.Id != previousRecord.Id { + if err := s.update(previousRecord); err != nil { + log.Printf("failed to update record %s: %s", previousRecord.Id, err) + } + previousRecord = currentRecord + s.save(currentRecord) + } + } + } +} + +func (s *Scrobbler) save(record *Record) error { + _, err := s.db.Exec("insert into records(id, title, artist, album, duration, playtime, time) values(?, ?, ?, ?, ?, 0, ?)", + record.Id, + record.Title, + record.Artist, + record.Album, + int(record.Duration.Seconds()), + record.Timestamp, + ) + return err +} + +func (s *Scrobbler) update(record *Record) error { + tnow := time.Now() + playtime := tnow.Sub(record.Timestamp).Seconds() + _, err := s.db.Exec("update records set playtime = ? where id = ?", + int(playtime), + record.Id, + ) + return err +} |
