feat: time-gated imports via cfg

pull/20/head
Gabe Farrell 6 months ago
parent 6d000d87e4
commit c14df8c2fb

@ -6,6 +6,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"time"
) )
const ( const (
@ -37,6 +38,8 @@ const (
ALLOWED_HOSTS_ENV = "KOITO_ALLOWED_HOSTS" ALLOWED_HOSTS_ENV = "KOITO_ALLOWED_HOSTS"
DISABLE_RATE_LIMIT_ENV = "KOITO_DISABLE_RATE_LIMIT" DISABLE_RATE_LIMIT_ENV = "KOITO_DISABLE_RATE_LIMIT"
THROTTLE_IMPORTS_MS = "KOITO_THROTTLE_IMPORTS_MS" THROTTLE_IMPORTS_MS = "KOITO_THROTTLE_IMPORTS_MS"
IMPORT_BEFORE_UNIX_ENV = "KOITO_IMPORT_BEFORE_UNIX"
IMPORT_AFTER_UNIX_ENV = "KOITO_IMPORT_AFTER_UNIX"
) )
type config struct { type config struct {
@ -64,6 +67,8 @@ type config struct {
disableRateLimit bool disableRateLimit bool
importThrottleMs int importThrottleMs int
userAgent string userAgent string
importBefore time.Time
importAfter time.Time
} }
var ( var (
@ -112,6 +117,16 @@ func loadConfig(getenv func(string) string) (*config, error) {
cfg.lbzRelayUrl = getenv(LBZ_RELAY_URL_ENV) cfg.lbzRelayUrl = getenv(LBZ_RELAY_URL_ENV)
} }
beforeutx, _ := strconv.ParseInt(getenv(IMPORT_BEFORE_UNIX_ENV), 10, 64)
afterutx, _ := strconv.ParseInt(getenv(IMPORT_AFTER_UNIX_ENV), 10, 64)
if beforeutx > 0 {
cfg.importBefore = time.Unix(beforeutx, 0)
}
if afterutx > 0 {
cfg.importAfter = time.Unix(afterutx, 0)
}
cfg.importThrottleMs, _ = strconv.Atoi(getenv(THROTTLE_IMPORTS_MS)) cfg.importThrottleMs, _ = strconv.Atoi(getenv(THROTTLE_IMPORTS_MS))
cfg.disableRateLimit = parseBool(getenv(DISABLE_RATE_LIMIT_ENV)) cfg.disableRateLimit = parseBool(getenv(DISABLE_RATE_LIMIT_ENV))
@ -308,3 +323,8 @@ func ThrottleImportMs() int {
defer lock.RUnlock() defer lock.RUnlock()
return globalConfig.importThrottleMs return globalConfig.importThrottleMs
} }
// returns the before, after times, in that order
func ImportWindow() (time.Time, time.Time) {
return globalConfig.importBefore, globalConfig.importAfter
}

@ -4,11 +4,13 @@ import (
"context" "context"
"os" "os"
"path" "path"
"time"
"github.com/gabehf/koito/internal/cfg" "github.com/gabehf/koito/internal/cfg"
"github.com/gabehf/koito/internal/logger" "github.com/gabehf/koito/internal/logger"
) )
// runs after every importer
func finishImport(ctx context.Context, filename string, numImported int) error { func finishImport(ctx context.Context, filename string, numImported int) error {
l := logger.FromContext(ctx) l := logger.FromContext(ctx)
_, err := os.Stat(path.Join(cfg.ConfigDir(), "import_complete")) _, err := os.Stat(path.Join(cfg.ConfigDir(), "import_complete"))
@ -27,3 +29,18 @@ func finishImport(ctx context.Context, filename string, numImported int) error {
} }
return nil return nil
} }
// from https://stackoverflow.com/a/55093788 with modification to use cfg and check for zero values
func inImportTimeWindow(check time.Time) bool {
end, start := cfg.ImportWindow()
if start.IsZero() && end.IsZero() {
return true
}
if !start.IsZero() && end.IsZero() {
return !check.Before(start)
}
if start.IsZero() && !end.IsZero() {
return !check.After(end)
}
return !check.Before(start) && !check.After(end)
}

@ -93,6 +93,10 @@ func ImportLastFMFile(ctx context.Context, store db.DB, mbzc mbz.MusicBrainzCall
} else { } else {
ts = time.Unix(unix, 0).UTC() ts = time.Unix(unix, 0).UTC()
} }
if !inImportTimeWindow(ts) {
l.Debug().Msgf("Skipping import due to import time rules")
continue
}
opts := catalog.SubmitListenOpts{ opts := catalog.SubmitListenOpts{
MbzCaller: mbzc, MbzCaller: mbzc,
Artist: track.Artist.Text, Artist: track.Artist.Text,

@ -78,6 +78,11 @@ func ImportListenBrainzFile(ctx context.Context, store db.DB, mbzc mbz.MusicBrai
fmt.Println("Error unmarshaling JSON:", err) fmt.Println("Error unmarshaling JSON:", err)
continue continue
} }
ts := time.Unix(payload.ListenedAt, 0)
if !inImportTimeWindow(ts) {
l.Debug().Msgf("Skipping import due to import time rules")
continue
}
artistMbzIDs, err := utils.ParseUUIDSlice(payload.TrackMeta.AdditionalInfo.ArtistMBIDs) artistMbzIDs, err := utils.ParseUUIDSlice(payload.TrackMeta.AdditionalInfo.ArtistMBIDs)
if err != nil { if err != nil {
l.Debug().Err(err).Msg("Failed to parse one or more uuids") l.Debug().Err(err).Msg("Failed to parse one or more uuids")
@ -119,7 +124,7 @@ func ImportListenBrainzFile(ctx context.Context, store db.DB, mbzc mbz.MusicBrai
ReleaseMbzID: releaseMbzID, ReleaseMbzID: releaseMbzID,
ReleaseGroupMbzID: rgMbzID, ReleaseGroupMbzID: rgMbzID,
Duration: duration, Duration: duration,
Time: time.Unix(payload.ListenedAt, 0), Time: ts,
UserID: 1, UserID: 1,
Client: client, Client: client,
} }

@ -65,14 +65,18 @@ func ImportMalojaFile(ctx context.Context, store db.DB, filename string) error {
l.Debug().Msg("Skipping invalid maloja import item") l.Debug().Msg("Skipping invalid maloja import item")
continue continue
} }
ts := time.Unix(item.Time, 0).UTC() ts := time.Unix(item.Time, 0)
if !inImportTimeWindow(ts) {
l.Debug().Msgf("Skipping import due to import time rules")
continue
}
opts := catalog.SubmitListenOpts{ opts := catalog.SubmitListenOpts{
MbzCaller: &mbz.MusicBrainzClient{}, MbzCaller: &mbz.MusicBrainzClient{},
Artist: item.Track.Artists[0], Artist: item.Track.Artists[0],
ArtistNames: artists, ArtistNames: artists,
TrackTitle: item.Track.Title, TrackTitle: item.Track.Title,
ReleaseTitle: item.Track.Album.Title, ReleaseTitle: item.Track.Album.Title,
Time: ts, Time: ts.Local(),
UserID: 1, UserID: 1,
} }
err = catalog.SubmitListen(ctx, store, opts) err = catalog.SubmitListen(ctx, store, opts)

@ -43,10 +43,15 @@ func ImportSpotifyFile(ctx context.Context, store db.DB, filename string) error
if err != nil { if err != nil {
return err return err
} }
for _, item := range export { for _, item := range export {
if item.ReasonEnd != "trackdone" { if item.ReasonEnd != "trackdone" {
continue continue
} }
if !inImportTimeWindow(item.Timestamp) {
l.Debug().Msgf("Skipping import due to import time rules")
continue
}
dur := item.MsPlayed dur := item.MsPlayed
if item.TrackName == "" || item.ArtistName == "" { if item.TrackName == "" || item.ArtistName == "" {
l.Debug().Msg("Skipping non-track item") l.Debug().Msg("Skipping non-track item")
@ -58,7 +63,7 @@ func ImportSpotifyFile(ctx context.Context, store db.DB, filename string) error
TrackTitle: item.TrackName, TrackTitle: item.TrackName,
ReleaseTitle: item.AlbumName, ReleaseTitle: item.AlbumName,
Duration: dur / 1000, Duration: dur / 1000,
Time: item.Timestamp.UTC(), Time: item.Timestamp,
UserID: 1, UserID: 1,
} }
err = catalog.SubmitListen(ctx, store, opts) err = catalog.SubmitListen(ctx, store, opts)

Loading…
Cancel
Save