From 48c8843f91a05cd73f0b2dfbe02c77872e3170c2 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Sun, 12 Nov 2023 01:14:53 +0100 Subject: [PATCH] Moved specifc backends into separate packages --- backends/{interfaces.go => backends.go} | 61 ++++++------------- .../{interfaces_test.go => backends_test.go} | 10 +-- backends/{ => dump}/dump.go | 12 ++-- backends/funkwhale/client.go | 2 +- backends/funkwhale/client_test.go | 4 +- backends/{ => funkwhale}/funkwhale.go | 13 ++-- backends/{ => funkwhale}/funkwhale_test.go | 7 +-- backends/listenbrainz/client.go | 2 +- backends/listenbrainz/client_test.go | 4 +- backends/{ => listenbrainz}/listenbrainz.go | 13 ++-- .../{ => listenbrainz}/listenbrainz_test.go | 6 +- backends/maloja/client.go | 2 +- backends/{ => maloja}/maloja.go | 11 ++-- backends/{ => scrobblerlog}/scrobblerlog.go | 15 +++-- cmd/listens.go | 5 +- cmd/loves.go | 5 +- models/interfaces.go | 53 ++++++++++++++++ 17 files changed, 127 insertions(+), 98 deletions(-) rename backends/{interfaces.go => backends.go} (66%) rename backends/{interfaces_test.go => backends_test.go} (87%) rename backends/{ => dump}/dump.go (88%) rename backends/{ => funkwhale}/funkwhale.go (90%) rename backends/{ => funkwhale}/funkwhale_test.go (93%) rename backends/{ => listenbrainz}/listenbrainz.go (90%) rename backends/{ => listenbrainz}/listenbrainz_test.go (94%) rename backends/{ => maloja}/maloja.go (91%) rename backends/{ => scrobblerlog}/scrobblerlog.go (84%) create mode 100644 models/interfaces.go diff --git a/backends/interfaces.go b/backends/backends.go similarity index 66% rename from backends/interfaces.go rename to backends/backends.go index fde0e05..3cb3444 100644 --- a/backends/interfaces.go +++ b/backends/backends.go @@ -26,37 +26,16 @@ import ( "fmt" "reflect" "strings" - "time" "github.com/spf13/viper" + "go.uploadedlobster.com/scotty/backends/dump" + "go.uploadedlobster.com/scotty/backends/funkwhale" + "go.uploadedlobster.com/scotty/backends/listenbrainz" + "go.uploadedlobster.com/scotty/backends/maloja" + "go.uploadedlobster.com/scotty/backends/scrobblerlog" "go.uploadedlobster.com/scotty/models" ) -type Backend interface { - FromConfig(config *viper.Viper) Backend -} - -type ListenExport interface { - ExportListens(oldestTimestamp time.Time) ([]models.Listen, error) -} - -type ListenImport interface { - ImportListens(listens []models.Listen, oldestTimestamp time.Time) (ImportResult, error) -} - -type LovesExport interface { - ExportLoves(oldestTimestamp time.Time) ([]models.Love, error) -} - -type LovesImport interface { - ImportLoves(loves []models.Love, oldestTimestamp time.Time) (ImportResult, error) -} - -type ImportResult struct { - Count int - LastTimestamp time.Time -} - type BackendInfo struct { Name string ExportCapabilities []Capability @@ -96,15 +75,15 @@ func GetBackends() []BackendInfo { return backends } -var knownBackends = map[string]func() Backend{ - "dump": func() Backend { return &DumpBackend{} }, - "funkwhale-api": func() Backend { return &FunkwhaleApiBackend{} }, - "listenbrainz-api": func() Backend { return &ListenBrainzApiBackend{} }, - "maloja-api": func() Backend { return &MalojaApiBackend{} }, - "scrobbler-log": func() Backend { return &ScrobblerLogBackend{} }, +var knownBackends = map[string]func() models.Backend{ + "dump": func() models.Backend { return &dump.DumpBackend{} }, + "funkwhale-api": func() models.Backend { return &funkwhale.FunkwhaleApiBackend{} }, + "listenbrainz-api": func() models.Backend { return &listenbrainz.ListenBrainzApiBackend{} }, + "maloja-api": func() models.Backend { return &maloja.MalojaApiBackend{} }, + "scrobbler-log": func() models.Backend { return &scrobblerlog.ScrobblerLogBackend{} }, } -func resolveBackend(config *viper.Viper) (string, Backend, error) { +func resolveBackend(config *viper.Viper) (string, models.Backend, error) { backendName := config.GetString("backend") backendType := knownBackends[backendName] if backendType == nil { @@ -113,43 +92,43 @@ func resolveBackend(config *viper.Viper) (string, Backend, error) { return backendName, backendType().FromConfig(config), nil } -func implementsInterface[T interface{}](backend Backend) (bool, string) { +func implementsInterface[T interface{}](backend models.Backend) (bool, string) { expectedInterface := reflect.TypeOf((*T)(nil)).Elem() implements := backend != nil && reflect.TypeOf(backend).Implements(expectedInterface) return implements, expectedInterface.Name() } -func getExportCapabilities(backend Backend) []string { +func getExportCapabilities(backend models.Backend) []string { caps := make([]Capability, 0) var name string var found bool - name, found = checkCapability[ListenExport](backend, "export") + name, found = checkCapability[models.ListenExport](backend, "export") if found { caps = append(caps, name) } - name, found = checkCapability[LovesExport](backend, "export") + name, found = checkCapability[models.LovesExport](backend, "export") if found { caps = append(caps, name) } return caps } -func getImportCapabilities(backend Backend) []Capability { +func getImportCapabilities(backend models.Backend) []Capability { caps := make([]Capability, 0) var name string var found bool - name, found = checkCapability[ListenImport](backend, "import") + name, found = checkCapability[models.ListenImport](backend, "import") if found { caps = append(caps, name) } - name, found = checkCapability[LovesImport](backend, "import") + name, found = checkCapability[models.LovesImport](backend, "import") if found { caps = append(caps, name) } return caps } -func checkCapability[T interface{}](backend Backend, suffix string) (string, bool) { +func checkCapability[T interface{}](backend models.Backend, suffix string) (string, bool) { implements, name := implementsInterface[T](backend) if implements { cap, found := strings.CutSuffix(strings.ToLower(name), suffix) diff --git a/backends/interfaces_test.go b/backends/backends_test.go similarity index 87% rename from backends/interfaces_test.go rename to backends/backends_test.go index 8dab766..d70ca4f 100644 --- a/backends/interfaces_test.go +++ b/backends/backends_test.go @@ -28,27 +28,29 @@ import ( "github.com/spf13/viper" "github.com/stretchr/testify/assert" "go.uploadedlobster.com/scotty/backends" + "go.uploadedlobster.com/scotty/backends/dump" + "go.uploadedlobster.com/scotty/models" ) func TestResolveBackend(t *testing.T) { config := viper.New() config.Set("backend", "dump") - backend, err := backends.ResolveBackend[backends.ListenImport](config) + backend, err := backends.ResolveBackend[models.ListenImport](config) assert.NoError(t, err) - assert.IsType(t, backends.DumpBackend{}, backend) + assert.IsType(t, dump.DumpBackend{}, backend) } func TestResolveBackendUnknown(t *testing.T) { config := viper.New() config.Set("backend", "foo") - _, err := backends.ResolveBackend[backends.ListenImport](config) + _, err := backends.ResolveBackend[models.ListenImport](config) assert.EqualError(t, err, "Unknown backend foo") } func TestResolveBackendInvalidInterface(t *testing.T) { config := viper.New() config.Set("backend", "dump") - _, err := backends.ResolveBackend[backends.ListenExport](config) + _, err := backends.ResolveBackend[models.ListenExport](config) assert.EqualError(t, err, "Backend dump does not implement ListenExport") } diff --git a/backends/dump.go b/backends/dump/dump.go similarity index 88% rename from backends/dump.go rename to backends/dump/dump.go index a6bf59c..eeff3a9 100644 --- a/backends/dump.go +++ b/backends/dump/dump.go @@ -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 THE SOFTWARE. */ -package backends +package dump import ( "fmt" @@ -31,12 +31,12 @@ import ( type DumpBackend struct{} -func (b DumpBackend) FromConfig(config *viper.Viper) Backend { +func (b DumpBackend) FromConfig(config *viper.Viper) models.Backend { return b } -func (b DumpBackend) ImportListens(listens []models.Listen, oldestTimestamp time.Time) (ImportResult, error) { - result := ImportResult{ +func (b DumpBackend) ImportListens(listens []models.Listen, oldestTimestamp time.Time) (models.ImportResult, error) { + result := models.ImportResult{ Count: len(listens), LastTimestamp: oldestTimestamp, } @@ -49,8 +49,8 @@ func (b DumpBackend) ImportListens(listens []models.Listen, oldestTimestamp time return result, nil } -func (b DumpBackend) ImportLoves(loves []models.Love, oldestTimestamp time.Time) (ImportResult, error) { - result := ImportResult{ +func (b DumpBackend) ImportLoves(loves []models.Love, oldestTimestamp time.Time) (models.ImportResult, error) { + result := models.ImportResult{ Count: len(loves), LastTimestamp: oldestTimestamp, } diff --git a/backends/funkwhale/client.go b/backends/funkwhale/client.go index 0aa2d46..2b32453 100644 --- a/backends/funkwhale/client.go +++ b/backends/funkwhale/client.go @@ -35,7 +35,7 @@ type Client struct { token string } -func New(serverUrl string, token string) Client { +func NewClient(serverUrl string, token string) Client { resty := resty.New() resty.SetBaseURL(serverUrl) resty.SetAuthScheme("Bearer") diff --git a/backends/funkwhale/client_test.go b/backends/funkwhale/client_test.go index d2bcca1..c85317b 100644 --- a/backends/funkwhale/client_test.go +++ b/backends/funkwhale/client_test.go @@ -34,7 +34,7 @@ import ( func TestNewClient(t *testing.T) { serverUrl := "https://funkwhale.example.com" token := "foobar123" - client := funkwhale.New(serverUrl, token) + client := funkwhale.NewClient(serverUrl, token) assert.Equal(t, serverUrl, client.HttpClient.BaseURL) assert.Equal(t, token, client.HttpClient.Token) } @@ -44,7 +44,7 @@ func TestGetHistoryListenings(t *testing.T) { token := "thetoken" serverUrl := "https://funkwhale.example.com" - client := funkwhale.New(serverUrl, token) + client := funkwhale.NewClient(serverUrl, token) setupHttpMock(t, client.HttpClient.GetClient(), "https://funkwhale.example.com/api/v1/history/listenings", "testdata/listenings.json") diff --git a/backends/funkwhale.go b/backends/funkwhale/funkwhale.go similarity index 90% rename from backends/funkwhale.go rename to backends/funkwhale/funkwhale.go index f074858..7666e7d 100644 --- a/backends/funkwhale.go +++ b/backends/funkwhale/funkwhale.go @@ -19,26 +19,25 @@ 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 THE SOFTWARE. */ -package backends +package funkwhale import ( "slices" "time" "github.com/spf13/viper" - "go.uploadedlobster.com/scotty/backends/funkwhale" "go.uploadedlobster.com/scotty/models" ) const FunkwhaleClientName = "Funkwhale" type FunkwhaleApiBackend struct { - client funkwhale.Client + client Client username string } -func (b FunkwhaleApiBackend) FromConfig(config *viper.Viper) Backend { - b.client = funkwhale.New( +func (b FunkwhaleApiBackend) FromConfig(config *viper.Viper) models.Backend { + b.client = NewClient( config.GetString("server-url"), config.GetString("token"), ) @@ -48,7 +47,7 @@ func (b FunkwhaleApiBackend) FromConfig(config *viper.Viper) Backend { func (b FunkwhaleApiBackend) ExportListens(oldestTimestamp time.Time) ([]models.Listen, error) { page := 1 - perPage := funkwhale.MaxItemsPerGet + perPage := MaxItemsPerGet listens := make([]models.Listen, 0) @@ -85,7 +84,7 @@ out: return listens, nil } -func ListenFromFunkwhale(fwListen funkwhale.Listening) models.Listen { +func ListenFromFunkwhale(fwListen Listening) models.Listen { track := fwListen.Track listen := models.Listen{ UserName: fwListen.User.UserName, diff --git a/backends/funkwhale_test.go b/backends/funkwhale/funkwhale_test.go similarity index 93% rename from backends/funkwhale_test.go rename to backends/funkwhale/funkwhale_test.go index 541a104..e8b1e63 100644 --- a/backends/funkwhale_test.go +++ b/backends/funkwhale/funkwhale_test.go @@ -19,14 +19,13 @@ 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 THE SOFTWARE. */ -package backends_test +package funkwhale_test import ( "testing" "time" "github.com/stretchr/testify/assert" - "go.uploadedlobster.com/scotty/backends" "go.uploadedlobster.com/scotty/backends/funkwhale" "go.uploadedlobster.com/scotty/models" ) @@ -58,7 +57,7 @@ func TestListenFromFunkwhale(t *testing.T) { }, }, } - listen := backends.ListenFromFunkwhale(fwListen) + listen := funkwhale.ListenFromFunkwhale(fwListen) assert.Equal(t, time.Unix(1699574369, 0).Unix(), listen.ListenedAt.Unix()) assert.Equal(t, fwListen.User.UserName, listen.UserName) assert.Equal(t, time.Duration(414*time.Second), listen.Duration) @@ -71,5 +70,5 @@ func TestListenFromFunkwhale(t *testing.T) { assert.Equal(t, models.MBID(fwListen.Track.RecordingMbid), listen.RecordingMbid) assert.Equal(t, models.MBID(fwListen.Track.Album.ReleaseMbid), listen.ReleaseMbid) assert.Equal(t, models.MBID(fwListen.Track.Artist.ArtistMbid), listen.ArtistMbids[0]) - assert.Equal(t, backends.FunkwhaleClientName, listen.AdditionalInfo["media_player"]) + assert.Equal(t, funkwhale.FunkwhaleClientName, listen.AdditionalInfo["media_player"]) } diff --git a/backends/listenbrainz/client.go b/backends/listenbrainz/client.go index f3a9b77..8ab1c9b 100644 --- a/backends/listenbrainz/client.go +++ b/backends/listenbrainz/client.go @@ -38,7 +38,7 @@ type Client struct { MaxResults int } -func New(token string) Client { +func NewClient(token string) Client { resty := resty.New() resty.SetBaseURL(listenBrainzBaseURL) resty.SetAuthScheme("Token") diff --git a/backends/listenbrainz/client_test.go b/backends/listenbrainz/client_test.go index 7334378..c650830 100644 --- a/backends/listenbrainz/client_test.go +++ b/backends/listenbrainz/client_test.go @@ -34,7 +34,7 @@ import ( func TestNewClient(t *testing.T) { token := "foobar123" - client := listenbrainz.New(token) + client := listenbrainz.NewClient(token) assert.Equal(t, token, client.HttpClient.Token) assert.Equal(t, listenbrainz.DefaultItemsPerGet, client.MaxResults) } @@ -43,7 +43,7 @@ func TestGetListens(t *testing.T) { defer httpmock.DeactivateAndReset() token := "thetoken" - client := listenbrainz.New(token) + client := listenbrainz.NewClient(token) setupHttpMock(t, client.HttpClient.GetClient(), "https://api.listenbrainz.org/1/user/outsidecontext/listens", "testdata/listens.json") diff --git a/backends/listenbrainz.go b/backends/listenbrainz/listenbrainz.go similarity index 90% rename from backends/listenbrainz.go rename to backends/listenbrainz/listenbrainz.go index 1c34d6d..369c80f 100644 --- a/backends/listenbrainz.go +++ b/backends/listenbrainz/listenbrainz.go @@ -19,25 +19,24 @@ 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 THE SOFTWARE. */ -package backends +package listenbrainz import ( "slices" "time" "github.com/spf13/viper" - "go.uploadedlobster.com/scotty/backends/listenbrainz" "go.uploadedlobster.com/scotty/models" ) type ListenBrainzApiBackend struct { - client listenbrainz.Client + client Client username string } -func (b ListenBrainzApiBackend) FromConfig(config *viper.Viper) Backend { - b.client = listenbrainz.New(config.GetString("token")) - b.client.MaxResults = listenbrainz.MaxItemsPerGet +func (b ListenBrainzApiBackend) FromConfig(config *viper.Viper) models.Backend { + b.client = NewClient(config.GetString("token")) + b.client.MaxResults = MaxItemsPerGet b.username = config.GetString("username") return b } @@ -77,7 +76,7 @@ out: return listens, nil } -func ListenFromListenBrainz(lbListen listenbrainz.Listen) models.Listen { +func ListenFromListenBrainz(lbListen Listen) models.Listen { track := lbListen.TrackMetadata listen := models.Listen{ ListenedAt: time.Unix(lbListen.ListenedAt, 0), diff --git a/backends/listenbrainz_test.go b/backends/listenbrainz/listenbrainz_test.go similarity index 94% rename from backends/listenbrainz_test.go rename to backends/listenbrainz/listenbrainz_test.go index 5b82986..81c236f 100644 --- a/backends/listenbrainz_test.go +++ b/backends/listenbrainz/listenbrainz_test.go @@ -19,14 +19,13 @@ 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 THE SOFTWARE. */ -package backends_test +package listenbrainz_test import ( "testing" "time" "github.com/stretchr/testify/assert" - "go.uploadedlobster.com/scotty/backends" "go.uploadedlobster.com/scotty/backends/listenbrainz" "go.uploadedlobster.com/scotty/models" ) @@ -50,7 +49,7 @@ func TestListenFromListenBrainz(t *testing.T) { }, }, } - listen := backends.ListenFromListenBrainz(lbListen) + listen := listenbrainz.ListenFromListenBrainz(lbListen) assert.Equal(t, time.Unix(1699289873, 0), listen.ListenedAt) assert.Equal(t, lbListen.UserName, listen.UserName) assert.Equal(t, time.Duration(528235*time.Millisecond), listen.Duration) @@ -58,7 +57,6 @@ func TestListenFromListenBrainz(t *testing.T) { assert.Equal(t, lbListen.TrackMetadata.ReleaseName, listen.ReleaseName) assert.Equal(t, []string{lbListen.TrackMetadata.ArtistName}, listen.ArtistNames) assert.Equal(t, 8, listen.TrackNumber) - assert.Equal(t, 8, listen.TrackNumber) assert.Equal(t, models.MBID("e225fb84-dc9a-419e-adcd-9890f59ec432"), listen.RecordingMbid) assert.Equal(t, models.MBID("d7f22677-9803-4d21-ba42-081b633a6f68"), listen.ReleaseMbid) assert.Equal(t, models.MBID("80aca1ee-aa51-41be-9f75-024710d92ff4"), listen.ReleaseGroupMbid) diff --git a/backends/maloja/client.go b/backends/maloja/client.go index 6c3cf11..c8a4df2 100644 --- a/backends/maloja/client.go +++ b/backends/maloja/client.go @@ -32,7 +32,7 @@ type Client struct { token string } -func New(serverUrl string, token string) Client { +func NewClient(serverUrl string, token string) Client { resty := resty.New() resty.SetBaseURL(serverUrl) resty.SetHeader("Accept", "application/json") diff --git a/backends/maloja.go b/backends/maloja/maloja.go similarity index 91% rename from backends/maloja.go rename to backends/maloja/maloja.go index 0269e7a..7f7f7b6 100644 --- a/backends/maloja.go +++ b/backends/maloja/maloja.go @@ -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 THE SOFTWARE. */ -package backends +package maloja import ( "slices" @@ -27,16 +27,15 @@ import ( "time" "github.com/spf13/viper" - "go.uploadedlobster.com/scotty/backends/maloja" "go.uploadedlobster.com/scotty/models" ) type MalojaApiBackend struct { - client maloja.Client + client Client } -func (b MalojaApiBackend) FromConfig(config *viper.Viper) Backend { - b.client = maloja.New( +func (b MalojaApiBackend) FromConfig(config *viper.Viper) models.Backend { + b.client = NewClient( config.GetString("server-url"), config.GetString("token"), ) @@ -76,7 +75,7 @@ out: return listens, nil } -func ListenFromMaloja(mlListen maloja.Listen) models.Listen { +func ListenFromMaloja(mlListen Listen) models.Listen { track := mlListen.Track listen := models.Listen{ ListenedAt: time.Unix(mlListen.ListenedAt, 0), diff --git a/backends/scrobblerlog.go b/backends/scrobblerlog/scrobblerlog.go similarity index 84% rename from backends/scrobblerlog.go rename to backends/scrobblerlog/scrobblerlog.go index efda58f..7f20db3 100644 --- a/backends/scrobblerlog.go +++ b/backends/scrobblerlog/scrobblerlog.go @@ -19,14 +19,13 @@ 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 THE SOFTWARE. */ -package backends +package scrobblerlog import ( "os" "time" "github.com/spf13/viper" - "go.uploadedlobster.com/scotty/backends/scrobblerlog" "go.uploadedlobster.com/scotty/models" ) @@ -35,7 +34,7 @@ type ScrobblerLogBackend struct { includeSkipped bool } -func (b ScrobblerLogBackend) FromConfig(config *viper.Viper) Backend { +func (b ScrobblerLogBackend) FromConfig(config *viper.Viper) models.Backend { b.filePath = config.GetString("file-path") b.includeSkipped = config.GetBool("include-skipped") return b @@ -49,7 +48,7 @@ func (b ScrobblerLogBackend) ExportListens(oldestTimestamp time.Time) ([]models. defer file.Close() - result, err := scrobblerlog.Parse(file, b.includeSkipped) + result, err := Parse(file, b.includeSkipped) if err != nil { return nil, err } @@ -57,8 +56,8 @@ func (b ScrobblerLogBackend) ExportListens(oldestTimestamp time.Time) ([]models. return result.Listens, nil } -func (b ScrobblerLogBackend) ImportListens(listens []models.Listen, oldestTimestamp time.Time) (ImportResult, error) { - result := ImportResult{ +func (b ScrobblerLogBackend) ImportListens(listens []models.Listen, oldestTimestamp time.Time) (models.ImportResult, error) { + result := models.ImportResult{ Count: 0, LastTimestamp: oldestTimestamp, } @@ -70,13 +69,13 @@ func (b ScrobblerLogBackend) ImportListens(listens []models.Listen, oldestTimest defer file.Close() - log := scrobblerlog.ScrobblerLog{ + log := ScrobblerLog{ Timezone: "UNKNOWN", Client: "Rockbox unknown $Revision$", Listens: listens, } - lastTimestamp, err := scrobblerlog.Write(file, &log) + lastTimestamp, err := Write(file, &log) if err != nil { return result, err diff --git a/cmd/listens.go b/cmd/listens.go index 36de419..9dd3a9b 100644 --- a/cmd/listens.go +++ b/cmd/listens.go @@ -27,6 +27,7 @@ import ( "github.com/spf13/cobra" "go.uploadedlobster.com/scotty/backends" + "go.uploadedlobster.com/scotty/models" ) // listensCmd represents the listens command @@ -38,9 +39,9 @@ var listensCmd = &cobra.Command{ sourceName, sourceConfig := getConfigFromFlag(cmd, "from") targetName, targetConfig := getConfigFromFlag(cmd, "to") fmt.Printf("Transferring listens from %s to %s...\n", sourceName, targetName) - exportBackend, err := backends.ResolveBackend[backends.ListenExport](sourceConfig) + exportBackend, err := backends.ResolveBackend[models.ListenExport](sourceConfig) cobra.CheckErr(err) - importBackend, err := backends.ResolveBackend[backends.ListenImport](targetConfig) + importBackend, err := backends.ResolveBackend[models.ListenImport](targetConfig) cobra.CheckErr(err) timestamp := time.Unix(0, 0) listens, err := exportBackend.ExportListens(timestamp) diff --git a/cmd/loves.go b/cmd/loves.go index a023496..859f415 100644 --- a/cmd/loves.go +++ b/cmd/loves.go @@ -27,6 +27,7 @@ import ( "github.com/spf13/cobra" "go.uploadedlobster.com/scotty/backends" + "go.uploadedlobster.com/scotty/models" ) // lovesCmd represents the loves command @@ -38,9 +39,9 @@ var lovesCmd = &cobra.Command{ sourceName, sourceConfig := getConfigFromFlag(cmd, "from") targetName, targetConfig := getConfigFromFlag(cmd, "to") fmt.Printf("Transferring loves from %s to %s...\n", sourceName, targetName) - exportBackend, err := backends.ResolveBackend[backends.LovesExport](sourceConfig) + exportBackend, err := backends.ResolveBackend[models.LovesExport](sourceConfig) cobra.CheckErr(err) - importBackend, err := backends.ResolveBackend[backends.LovesImport](targetConfig) + importBackend, err := backends.ResolveBackend[models.LovesImport](targetConfig) cobra.CheckErr(err) timestamp := time.Unix(0, 0) loves, err := exportBackend.ExportLoves(timestamp) diff --git a/models/interfaces.go b/models/interfaces.go new file mode 100644 index 0000000..95f2892 --- /dev/null +++ b/models/interfaces.go @@ -0,0 +1,53 @@ +/* +Copyright © 2023 Philipp Wolfer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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 +THE SOFTWARE. +*/ +package models + +import ( + "time" + + "github.com/spf13/viper" +) + +type Backend interface { + FromConfig(config *viper.Viper) Backend +} + +type ListenExport interface { + ExportListens(oldestTimestamp time.Time) ([]Listen, error) +} + +type ListenImport interface { + ImportListens(listens []Listen, oldestTimestamp time.Time) (ImportResult, error) +} + +type LovesExport interface { + ExportLoves(oldestTimestamp time.Time) ([]Love, error) +} + +type LovesImport interface { + ImportLoves(loves []Love, oldestTimestamp time.Time) (ImportResult, error) +} + +type ImportResult struct { + Count int + LastTimestamp time.Time +}