Move models to separate package

This allows easier reuse and better separation of code without introducing
circular dependencies
This commit is contained in:
Philipp Wolfer 2023-11-11 16:20:40 +01:00
parent cdddf89a3e
commit 9d97e324aa
No known key found for this signature in database
GPG key ID: 8FDF744D4919943B
8 changed files with 43 additions and 37 deletions

View file

@ -26,6 +26,7 @@ import (
"time" "time"
"github.com/spf13/viper" "github.com/spf13/viper"
"go.uploadedlobster.com/scotty/models"
) )
type DumpBackend struct{} type DumpBackend struct{}
@ -34,7 +35,7 @@ func (b DumpBackend) FromConfig(config *viper.Viper) Backend {
return b return b
} }
func (b DumpBackend) ImportListens(listens []Listen, oldestTimestamp time.Time) (ImportResult, error) { func (b DumpBackend) ImportListens(listens []models.Listen, oldestTimestamp time.Time) (ImportResult, error) {
result := ImportResult{ result := ImportResult{
Count: len(listens), Count: len(listens),
LastTimestamp: oldestTimestamp, LastTimestamp: oldestTimestamp,

View file

@ -29,6 +29,7 @@ import (
"time" "time"
"github.com/spf13/viper" "github.com/spf13/viper"
"go.uploadedlobster.com/scotty/models"
) )
type Backend interface { type Backend interface {
@ -36,19 +37,19 @@ type Backend interface {
} }
type ListenExport interface { type ListenExport interface {
ExportListens(oldestTimestamp time.Time) ([]Listen, error) ExportListens(oldestTimestamp time.Time) ([]models.Listen, error)
} }
type ListenImport interface { type ListenImport interface {
ImportListens(listens []Listen, oldestTimestamp time.Time) (ImportResult, error) ImportListens(listens []models.Listen, oldestTimestamp time.Time) (ImportResult, error)
} }
type LovesExport interface { type LovesExport interface {
ExportLoves(oldestTimestamp time.Time) ([]Love, error) ExportLoves(oldestTimestamp time.Time) ([]models.Love, error)
} }
type LovesImport interface { type LovesImport interface {
ExportLoves(loves []Love, oldestTimestamp time.Time) (ImportResult, error) ExportLoves(loves []models.Love, oldestTimestamp time.Time) (ImportResult, error)
} }
type ImportResult struct { type ImportResult struct {

View file

@ -27,6 +27,7 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
"go.uploadedlobster.com/scotty/backends/listenbrainz" "go.uploadedlobster.com/scotty/backends/listenbrainz"
"go.uploadedlobster.com/scotty/models"
) )
type ListenBrainzApiBackend struct { type ListenBrainzApiBackend struct {
@ -41,10 +42,10 @@ func (b ListenBrainzApiBackend) FromConfig(config *viper.Viper) Backend {
return b return b
} }
func (b ListenBrainzApiBackend) ExportListens(oldestTimestamp time.Time) ([]Listen, error) { func (b ListenBrainzApiBackend) ExportListens(oldestTimestamp time.Time) ([]models.Listen, error) {
maxTime := time.Now() maxTime := time.Now()
minTime := time.Unix(0, 0) minTime := time.Unix(0, 0)
listens := make([]Listen, 0) listens := make([]models.Listen, 0)
out: out:
for { for {
@ -63,7 +64,7 @@ out:
for _, listen := range result.Payload.Listens { for _, listen := range result.Payload.Listens {
if listen.ListenedAt > oldestTimestamp.Unix() { if listen.ListenedAt > oldestTimestamp.Unix() {
listens = append(listens, Listen{}.FromListenBrainz(listen)) listens = append(listens, ListenFromListenBrainz(listen))
} else { } else {
// result contains listens older then oldestTimestamp, // result contains listens older then oldestTimestamp,
// we can stop requesting more // we can stop requesting more
@ -76,20 +77,20 @@ out:
return listens, nil return listens, nil
} }
func (l Listen) FromListenBrainz(lbListen listenbrainz.Listen) Listen { func ListenFromListenBrainz(lbListen listenbrainz.Listen) models.Listen {
track := lbListen.TrackMetadata track := lbListen.TrackMetadata
listen := Listen{ listen := models.Listen{
ListenedAt: time.Unix(lbListen.ListenedAt, 0), ListenedAt: time.Unix(lbListen.ListenedAt, 0),
UserName: lbListen.UserName, UserName: lbListen.UserName,
Track: Track{ Track: models.Track{
TrackName: track.TrackName, TrackName: track.TrackName,
ReleaseName: track.ReleaseName, ReleaseName: track.ReleaseName,
ArtistNames: []string{track.ArtistName}, ArtistNames: []string{track.ArtistName},
Duration: track.Duration(), Duration: track.Duration(),
TrackNumber: track.TrackNumber(), TrackNumber: track.TrackNumber(),
RecordingMbid: MBID(track.RecordingMbid()), RecordingMbid: models.MBID(track.RecordingMbid()),
ReleaseMbid: MBID(track.ReleaseMbid()), ReleaseMbid: models.MBID(track.ReleaseMbid()),
ReleaseGroupMbid: MBID(track.ReleaseGroupMbid()), ReleaseGroupMbid: models.MBID(track.ReleaseGroupMbid()),
Isrc: track.Isrc(), Isrc: track.Isrc(),
AdditionalInfo: track.AdditionalInfo, AdditionalInfo: track.AdditionalInfo,
}, },

View file

@ -28,6 +28,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.uploadedlobster.com/scotty/backends" "go.uploadedlobster.com/scotty/backends"
"go.uploadedlobster.com/scotty/backends/listenbrainz" "go.uploadedlobster.com/scotty/backends/listenbrainz"
"go.uploadedlobster.com/scotty/models"
) )
func TestListenFromListenBrainz(t *testing.T) { func TestListenFromListenBrainz(t *testing.T) {
@ -49,7 +50,7 @@ func TestListenFromListenBrainz(t *testing.T) {
}, },
}, },
} }
listen := backends.Listen{}.FromListenBrainz(lbListen) listen := backends.ListenFromListenBrainz(lbListen)
assert.Equal(t, time.Unix(1699289873, 0), listen.ListenedAt) assert.Equal(t, time.Unix(1699289873, 0), listen.ListenedAt)
assert.Equal(t, lbListen.UserName, listen.UserName) assert.Equal(t, lbListen.UserName, listen.UserName)
assert.Equal(t, time.Duration(528235*time.Millisecond), listen.Duration) assert.Equal(t, time.Duration(528235*time.Millisecond), listen.Duration)
@ -58,9 +59,9 @@ func TestListenFromListenBrainz(t *testing.T) {
assert.Equal(t, []string{lbListen.TrackMetadata.ArtistName}, listen.ArtistNames) assert.Equal(t, []string{lbListen.TrackMetadata.ArtistName}, listen.ArtistNames)
assert.Equal(t, 8, listen.TrackNumber) assert.Equal(t, 8, listen.TrackNumber)
assert.Equal(t, 8, listen.TrackNumber) assert.Equal(t, 8, listen.TrackNumber)
assert.Equal(t, backends.MBID("e225fb84-dc9a-419e-adcd-9890f59ec432"), listen.RecordingMbid) assert.Equal(t, models.MBID("e225fb84-dc9a-419e-adcd-9890f59ec432"), listen.RecordingMbid)
assert.Equal(t, backends.MBID("d7f22677-9803-4d21-ba42-081b633a6f68"), listen.ReleaseMbid) assert.Equal(t, models.MBID("d7f22677-9803-4d21-ba42-081b633a6f68"), listen.ReleaseMbid)
assert.Equal(t, backends.MBID("80aca1ee-aa51-41be-9f75-024710d92ff4"), listen.ReleaseGroupMbid) assert.Equal(t, models.MBID("80aca1ee-aa51-41be-9f75-024710d92ff4"), listen.ReleaseGroupMbid)
assert.Equal(t, "DES561720901", listen.Isrc) assert.Equal(t, "DES561720901", listen.Isrc)
assert.Equal(t, lbListen.TrackMetadata.AdditionalInfo["foo"], listen.AdditionalInfo["foo"]) assert.Equal(t, lbListen.TrackMetadata.AdditionalInfo["foo"], listen.AdditionalInfo["foo"])
} }

View file

@ -28,6 +28,7 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
"go.uploadedlobster.com/scotty/backends/maloja" "go.uploadedlobster.com/scotty/backends/maloja"
"go.uploadedlobster.com/scotty/models"
) )
type MalojaApiBackend struct { type MalojaApiBackend struct {
@ -42,11 +43,11 @@ func (b MalojaApiBackend) FromConfig(config *viper.Viper) Backend {
return b return b
} }
func (b MalojaApiBackend) ExportListens(oldestTimestamp time.Time) ([]Listen, error) { func (b MalojaApiBackend) ExportListens(oldestTimestamp time.Time) ([]models.Listen, error) {
page := 0 page := 0
perPage := 1000 perPage := 1000
listens := make([]Listen, 0) listens := make([]models.Listen, 0)
out: out:
for { for {
@ -62,7 +63,7 @@ out:
for _, listen := range result.Listens { for _, listen := range result.Listens {
if listen.ListenedAt > oldestTimestamp.Unix() { if listen.ListenedAt > oldestTimestamp.Unix() {
listens = append(listens, Listen{}.FromMaloja(listen)) listens = append(listens, ListenFromMaloja(listen))
} else { } else {
break out break out
} }
@ -75,12 +76,12 @@ out:
return listens, nil return listens, nil
} }
func (l Listen) FromMaloja(mlListen maloja.Listen) Listen { func ListenFromMaloja(mlListen maloja.Listen) models.Listen {
track := mlListen.Track track := mlListen.Track
listen := Listen{ listen := models.Listen{
ListenedAt: time.Unix(mlListen.ListenedAt, 0), ListenedAt: time.Unix(mlListen.ListenedAt, 0),
PlaybackDuration: time.Duration(mlListen.Duration * int64(time.Second)), PlaybackDuration: time.Duration(mlListen.Duration * int64(time.Second)),
Track: Track{ Track: models.Track{
TrackName: track.Title, TrackName: track.Title,
ReleaseName: track.Album.Title, ReleaseName: track.Album.Title,
ArtistNames: track.Artists, ArtistNames: track.Artists,

View file

@ -33,6 +33,7 @@ import (
"time" "time"
"github.com/spf13/viper" "github.com/spf13/viper"
"go.uploadedlobster.com/scotty/models"
) )
type ScrobblerLogBackend struct { type ScrobblerLogBackend struct {
@ -46,7 +47,7 @@ func (b ScrobblerLogBackend) FromConfig(config *viper.Viper) Backend {
return b return b
} }
func (b ScrobblerLogBackend) ExportListens(oldestTimestamp time.Time) ([]Listen, error) { func (b ScrobblerLogBackend) ExportListens(oldestTimestamp time.Time) ([]models.Listen, error) {
file, err := os.Open(b.filePath) file, err := os.Open(b.filePath)
if err != nil { if err != nil {
return nil, err return nil, err
@ -65,7 +66,7 @@ func (b ScrobblerLogBackend) ExportListens(oldestTimestamp time.Time) ([]Listen,
// Row length is often flexible // Row length is often flexible
tsvReader.FieldsPerRecord = -1 tsvReader.FieldsPerRecord = -1
listens := make([]Listen, 0) listens := make([]models.Listen, 0)
for { for {
// A row is: // A row is:
// artistName releaseName trackName trackNumber duration rating timestamp recordingMbid // artistName releaseName trackName trackNumber duration rating timestamp recordingMbid
@ -101,7 +102,7 @@ func (b ScrobblerLogBackend) ExportListens(oldestTimestamp time.Time) ([]Listen,
return listens, nil return listens, nil
} }
func (b ScrobblerLogBackend) ImportListens(listens []Listen, oldestTimestamp time.Time) (ImportResult, error) { func (b ScrobblerLogBackend) ImportListens(listens []models.Listen, oldestTimestamp time.Time) (ImportResult, error) {
result := ImportResult{ result := ImportResult{
Count: 0, Count: 0,
LastTimestamp: oldestTimestamp, LastTimestamp: oldestTimestamp,
@ -195,8 +196,8 @@ func writeHeader(writer io.Writer) error {
return nil return nil
} }
func rowToListen(row []string, client string) (Listen, error) { func rowToListen(row []string, client string) (models.Listen, error) {
var listen Listen var listen models.Listen
trackNumber, err := strconv.Atoi(row[3]) trackNumber, err := strconv.Atoi(row[3])
if err != nil { if err != nil {
return listen, err return listen, err
@ -212,14 +213,14 @@ func rowToListen(row []string, client string) (Listen, error) {
return listen, err return listen, err
} }
listen = Listen{ listen = models.Listen{
Track: Track{ Track: models.Track{
ArtistNames: []string{row[0]}, ArtistNames: []string{row[0]},
ReleaseName: row[1], ReleaseName: row[1],
TrackName: row[2], TrackName: row[2],
TrackNumber: trackNumber, TrackNumber: trackNumber,
Duration: time.Duration(duration * int(time.Second)), Duration: time.Duration(duration * int(time.Second)),
AdditionalInfo: AdditionalInfo{ AdditionalInfo: models.AdditionalInfo{
"rockbox_rating": row[5], "rockbox_rating": row[5],
"media_player": client, "media_player": client,
}, },
@ -228,7 +229,7 @@ func rowToListen(row []string, client string) (Listen, error) {
} }
if len(row) > 7 { if len(row) > 7 {
listen.Track.RecordingMbid = MBID(row[7]) listen.Track.RecordingMbid = models.MBID(row[7])
} }
return listen, nil return listen, nil

View file

@ -19,7 +19,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
package backends package models
import ( import (
"strings" "strings"

View file

@ -19,17 +19,17 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
package backends_test package models_test
import ( import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.uploadedlobster.com/scotty/backends" "go.uploadedlobster.com/scotty/models"
) )
func TestTrackArtistName(t *testing.T) { func TestTrackArtistName(t *testing.T) {
track := backends.Track{ track := models.Track{
ArtistNames: []string{ ArtistNames: []string{
"Foo", "Foo",
"Bar", "Bar",