mirror of
https://git.sr.ht/~phw/scotty
synced 2025-04-16 10:09:28 +02:00
lastfm: listens export
This commit is contained in:
parent
267018901b
commit
f9d25e3b6f
2 changed files with 96 additions and 5 deletions
|
@ -11,6 +11,7 @@ Scotty transfers your listens/scrobbles and favorite tracks between various musi
|
|||
- Transfer loved tracks from Funkwhale to ListenBrainz
|
||||
- Submit listens stored in a Rockbox `.scrobbler.log` file to ListenBrainz, Last.fm or Maloja
|
||||
- Store your favorite tracks from Deezer as a JSPF playlist
|
||||
- Backup your listening history from ListenBrainz or Last.fm
|
||||
|
||||
|
||||
## Installation
|
||||
|
@ -44,7 +45,7 @@ deezer | ✓ | ⨯ | ✓ | -
|
|||
dump | ⨯ | ✓ | ⨯ | ✓
|
||||
funkwhale | ✓ | ⨯ | ✓ | -
|
||||
jspf | - | ✓ | - | ✓
|
||||
lastfm | - | - | ✓ | ✓
|
||||
lastfm | ✓ | ✓ | ✓ | ✓
|
||||
listenbrainz | ✓ | ✓ | ✓ | ✓
|
||||
maloja | ✓ | ✓ | ⨯ | ⨯
|
||||
scrobbler-log | ✓ | ✓ | ⨯ | ⨯
|
||||
|
|
|
@ -32,7 +32,9 @@ import (
|
|||
|
||||
const (
|
||||
MaxItemsPerGet = 1000
|
||||
MaxListensPerRequest = 50
|
||||
MaxListensPerGet = 200
|
||||
MaxListensPerSubmission = 50
|
||||
MaxPage = 1000000
|
||||
)
|
||||
|
||||
type LastfmApiBackend struct {
|
||||
|
@ -69,10 +71,98 @@ func (b *LastfmApiBackend) OAuth2Setup(token oauth2.TokenSource) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *LastfmApiBackend) ExportListens(oldestTimestamp time.Time, results chan models.ListensResult, progress chan models.Progress) {
|
||||
page := MaxPage
|
||||
minTime := oldestTimestamp
|
||||
perPage := MaxItemsPerGet
|
||||
|
||||
defer close(results)
|
||||
|
||||
// We need to gather the full list of listens in order to sort them
|
||||
p := models.Progress{Total: int64(page)}
|
||||
|
||||
out:
|
||||
for page > 0 {
|
||||
args := lastfm.P{
|
||||
"user": b.username,
|
||||
"limit": MaxListensPerGet,
|
||||
// last.fm includes the listen with the exact timestamp in the result
|
||||
"from": oldestTimestamp.Add(time.Second).Unix(),
|
||||
"page": page,
|
||||
}
|
||||
result, err := b.client.User.GetRecentTracks(args)
|
||||
if err != nil {
|
||||
results <- models.ListensResult{Error: err}
|
||||
progress <- p.Complete()
|
||||
return
|
||||
}
|
||||
|
||||
count := len(result.Tracks)
|
||||
if count == 0 {
|
||||
// The page was outside of the result range, adjust and request again
|
||||
if page > result.TotalPages {
|
||||
page = result.TotalPages
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
listens := make(models.ListensList, 0, 2*perPage)
|
||||
for _, scrobble := range result.Tracks {
|
||||
timestamp, err := strconv.ParseInt(scrobble.Date.Uts, 10, 64)
|
||||
if err != nil {
|
||||
results <- models.ListensResult{Error: err}
|
||||
progress <- p.Complete()
|
||||
break out
|
||||
}
|
||||
if timestamp > oldestTimestamp.Unix() {
|
||||
p.Elapsed += 1
|
||||
listen := models.Listen{
|
||||
ListenedAt: time.Unix(timestamp, 0),
|
||||
UserName: b.username,
|
||||
Track: models.Track{
|
||||
TrackName: scrobble.Name,
|
||||
ArtistNames: []string{},
|
||||
ReleaseName: scrobble.Album.Name,
|
||||
RecordingMbid: models.MBID(scrobble.Mbid),
|
||||
ArtistMbids: []models.MBID{},
|
||||
ReleaseMbid: models.MBID(scrobble.Album.Mbid),
|
||||
},
|
||||
}
|
||||
if scrobble.Artist.Name != "" {
|
||||
listen.Track.ArtistNames = []string{scrobble.Artist.Name}
|
||||
}
|
||||
if scrobble.Artist.Mbid != "" {
|
||||
listen.Track.ArtistMbids = []models.MBID{models.MBID(scrobble.Artist.Mbid)}
|
||||
}
|
||||
listens = append(listens, listen)
|
||||
} else {
|
||||
break out
|
||||
}
|
||||
}
|
||||
|
||||
sort.Sort(listens)
|
||||
minTime = listens[len(listens)-1].ListenedAt
|
||||
page -= 1
|
||||
|
||||
results <- models.ListensResult{
|
||||
Listens: listens,
|
||||
Total: result.Total,
|
||||
OldestTimestamp: minTime,
|
||||
}
|
||||
p.Total = int64(result.TotalPages)
|
||||
p.Elapsed = int64(result.TotalPages - page)
|
||||
progress <- p
|
||||
}
|
||||
|
||||
results <- models.ListensResult{OldestTimestamp: minTime}
|
||||
progress <- p.Complete()
|
||||
}
|
||||
|
||||
func (b *LastfmApiBackend) ImportListens(export models.ListensResult, importResult models.ImportResult, progress chan models.Progress) (models.ImportResult, error) {
|
||||
total := len(export.Listens)
|
||||
for i := 0; i < total; i += MaxListensPerRequest {
|
||||
listens := export.Listens[i:min(i+MaxListensPerRequest, total)]
|
||||
for i := 0; i < total; i += MaxListensPerSubmission {
|
||||
listens := export.Listens[i:min(i+MaxListensPerSubmission, total)]
|
||||
count := len(listens)
|
||||
if count == 0 {
|
||||
break
|
||||
|
|
Loading…
Add table
Reference in a new issue