mirror of
https://git.sr.ht/~phw/scotty
synced 2025-06-06 21:08:34 +02:00
Compare commits
5 commits
0a411fe2fa
...
91c28bac0c
Author | SHA1 | Date | |
---|---|---|---|
|
91c28bac0c | ||
|
21d757e37c | ||
|
c305b6c7e3 | ||
|
389c7c6ec1 | ||
|
e973e72bbe |
11 changed files with 29 additions and 24 deletions
|
@ -1,5 +1,14 @@
|
||||||
# Scotty Changelog
|
# Scotty Changelog
|
||||||
|
|
||||||
|
## 0.5.2 - 2025-05-01
|
||||||
|
- ListenBrainz: fixed loves export not considering latest timestamp
|
||||||
|
|
||||||
|
|
||||||
|
## 0.5.1 - 2025-05-01
|
||||||
|
- scrobblerlog: fixed timezone offset calculation
|
||||||
|
- if system locale detection fails don't abort but fall back to English
|
||||||
|
|
||||||
|
|
||||||
## 0.5.0 - 2025-04-29
|
## 0.5.0 - 2025-04-29
|
||||||
- ListenBrainz: handle missing loves metadata in case of merged recordings
|
- ListenBrainz: handle missing loves metadata in case of merged recordings
|
||||||
- ListenBrainz: fix loves import loading all existing loves
|
- ListenBrainz: fix loves import loading all existing loves
|
||||||
|
|
|
@ -117,7 +117,7 @@ out:
|
||||||
listens := make(models.ListensList, 0, perPage)
|
listens := make(models.ListensList, 0, perPage)
|
||||||
for _, track := range result.Tracks {
|
for _, track := range result.Tracks {
|
||||||
listen := track.AsListen()
|
listen := track.AsListen()
|
||||||
if listen.ListenedAt.Unix() > oldestTimestamp.Unix() {
|
if listen.ListenedAt.After(oldestTimestamp) {
|
||||||
listens = append(listens, listen)
|
listens = append(listens, listen)
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
|
@ -186,7 +186,7 @@ out:
|
||||||
loves := make(models.LovesList, 0, perPage)
|
loves := make(models.LovesList, 0, perPage)
|
||||||
for _, track := range result.Tracks {
|
for _, track := range result.Tracks {
|
||||||
love := track.AsLove()
|
love := track.AsLove()
|
||||||
if love.Created.Unix() > oldestTimestamp.Unix() {
|
if love.Created.After(oldestTimestamp) {
|
||||||
loves = append(loves, love)
|
loves = append(loves, love)
|
||||||
} else {
|
} else {
|
||||||
totalCount -= 1
|
totalCount -= 1
|
||||||
|
|
|
@ -84,7 +84,7 @@ out:
|
||||||
|
|
||||||
for _, fwListen := range result.Results {
|
for _, fwListen := range result.Results {
|
||||||
listen := fwListen.AsListen()
|
listen := fwListen.AsListen()
|
||||||
if listen.ListenedAt.Unix() > oldestTimestamp.Unix() {
|
if listen.ListenedAt.After(oldestTimestamp) {
|
||||||
p.Elapsed += 1
|
p.Elapsed += 1
|
||||||
listens = append(listens, listen)
|
listens = append(listens, listen)
|
||||||
} else {
|
} else {
|
||||||
|
@ -135,7 +135,7 @@ out:
|
||||||
|
|
||||||
for _, favorite := range result.Results {
|
for _, favorite := range result.Results {
|
||||||
love := favorite.AsLove()
|
love := favorite.AsLove()
|
||||||
if love.Created.Unix() > oldestTimestamp.Unix() {
|
if love.Created.After(oldestTimestamp) {
|
||||||
p.Elapsed += 1
|
p.Elapsed += 1
|
||||||
loves = append(loves, love)
|
loves = append(loves, love)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -199,7 +199,7 @@ func (b *ListenBrainzApiBackend) ExportLoves(oldestTimestamp time.Time, results
|
||||||
exportChan := make(chan models.LovesResult)
|
exportChan := make(chan models.LovesResult)
|
||||||
p := models.Progress{}
|
p := models.Progress{}
|
||||||
|
|
||||||
go b.exportLoves(time.Unix(0, 0), exportChan)
|
go b.exportLoves(oldestTimestamp, exportChan)
|
||||||
for existingLoves := range exportChan {
|
for existingLoves := range exportChan {
|
||||||
if existingLoves.Error != nil {
|
if existingLoves.Error != nil {
|
||||||
progress <- p.Complete()
|
progress <- p.Complete()
|
||||||
|
@ -219,7 +219,6 @@ func (b *ListenBrainzApiBackend) exportLoves(oldestTimestamp time.Time, results
|
||||||
offset := 0
|
offset := 0
|
||||||
defer close(results)
|
defer close(results)
|
||||||
loves := make(models.LovesList, 0, 2*MaxItemsPerGet)
|
loves := make(models.LovesList, 0, 2*MaxItemsPerGet)
|
||||||
p := models.Progress{}
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
for {
|
for {
|
||||||
|
@ -246,17 +245,13 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
love := feedback.AsLove()
|
love := feedback.AsLove()
|
||||||
if love.Created.Unix() > oldestTimestamp.Unix() {
|
if love.Created.After(oldestTimestamp) {
|
||||||
loves = append(loves, love)
|
loves = append(loves, love)
|
||||||
p.Elapsed += 1
|
|
||||||
} else {
|
} else {
|
||||||
break out
|
break out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Total = int64(result.TotalCount)
|
|
||||||
p.Elapsed += int64(count)
|
|
||||||
|
|
||||||
offset += MaxItemsPerGet
|
offset += MaxItemsPerGet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,7 @@ func (b *SpotifyApiBackend) ExportListens(oldestTimestamp time.Time, results cha
|
||||||
|
|
||||||
for _, listen := range result.Items {
|
for _, listen := range result.Items {
|
||||||
l := listen.AsListen()
|
l := listen.AsListen()
|
||||||
if l.ListenedAt.Unix() > oldestTimestamp.Unix() {
|
if l.ListenedAt.After(oldestTimestamp) {
|
||||||
listens = append(listens, l)
|
listens = append(listens, l)
|
||||||
} else {
|
} else {
|
||||||
// result contains listens older then oldestTimestamp
|
// result contains listens older then oldestTimestamp
|
||||||
|
@ -195,7 +195,7 @@ out:
|
||||||
loves := make(models.LovesList, 0, perPage)
|
loves := make(models.LovesList, 0, perPage)
|
||||||
for _, track := range result.Items {
|
for _, track := range result.Items {
|
||||||
love := track.AsLove()
|
love := track.AsLove()
|
||||||
if love.Created.Unix() > oldestTimestamp.Unix() {
|
if love.Created.After(oldestTimestamp) {
|
||||||
loves = append(loves, love)
|
loves = append(loves, love)
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -90,7 +90,7 @@ func (b *SubsonicApiBackend) filterSongs(songs []*subsonic.Child, oldestTimestam
|
||||||
loves := make(models.LovesList, 0, len(songs))
|
loves := make(models.LovesList, 0, len(songs))
|
||||||
for _, song := range songs {
|
for _, song := range songs {
|
||||||
love := SongAsLove(*song, b.client.User)
|
love := SongAsLove(*song, b.client.User)
|
||||||
if love.Created.Unix() > oldestTimestamp.Unix() {
|
if love.Created.After(oldestTimestamp) {
|
||||||
loves = append(loves, love)
|
loves = append(loves, love)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ func (c *TransferCmd[E, I, R]) Transfer(exp backends.ExportProcessor[R], imp bac
|
||||||
resultChan := make(chan models.ImportResult)
|
resultChan := make(chan models.ImportResult)
|
||||||
go imp.Process(exportChan, resultChan, importProgress)
|
go imp.Process(exportChan, resultChan, importProgress)
|
||||||
result := <-resultChan
|
result := <-resultChan
|
||||||
if result.LastTimestamp.Unix() < timestamp.Unix() {
|
if timestamp.After(result.LastTimestamp) {
|
||||||
result.LastTimestamp = timestamp
|
result.LastTimestamp = timestamp
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
@ -180,7 +180,7 @@ func (c *TransferCmd[E, I, R]) timestamp() (time.Time, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TransferCmd[E, I, R]) updateTimestamp(result models.ImportResult, oldTimestamp time.Time) error {
|
func (c *TransferCmd[E, I, R]) updateTimestamp(result models.ImportResult, oldTimestamp time.Time) error {
|
||||||
if result.LastTimestamp.Unix() < oldTimestamp.Unix() {
|
if oldTimestamp.After(result.LastTimestamp) {
|
||||||
result.LastTimestamp = oldTimestamp
|
result.LastTimestamp = oldTimestamp
|
||||||
}
|
}
|
||||||
printTimestamp("Latest timestamp: %v (%v)", result.LastTimestamp)
|
printTimestamp("Latest timestamp: %v (%v)", result.LastTimestamp)
|
||||||
|
|
|
@ -121,7 +121,7 @@ type ListensList []Listen
|
||||||
func (l ListensList) NewerThan(t time.Time) ListensList {
|
func (l ListensList) NewerThan(t time.Time) ListensList {
|
||||||
result := make(ListensList, 0, len(l))
|
result := make(ListensList, 0, len(l))
|
||||||
for _, item := range l {
|
for _, item := range l {
|
||||||
if item.ListenedAt.Unix() > t.Unix() {
|
if item.ListenedAt.After(t) {
|
||||||
result = append(result, item)
|
result = append(result, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ func (l ListensList) Len() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l ListensList) Less(i, j int) bool {
|
func (l ListensList) Less(i, j int) bool {
|
||||||
return l[i].ListenedAt.Unix() < l[j].ListenedAt.Unix()
|
return l[j].ListenedAt.After(l[i].ListenedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l ListensList) Swap(i, j int) {
|
func (l ListensList) Swap(i, j int) {
|
||||||
|
@ -147,7 +147,7 @@ func (l LovesList) Len() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l LovesList) Less(i, j int) bool {
|
func (l LovesList) Less(i, j int) bool {
|
||||||
return l[i].Created.Unix() < l[j].Created.Unix()
|
return l[j].Created.After(l[i].Created)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l LovesList) Swap(i, j int) {
|
func (l LovesList) Swap(i, j int) {
|
||||||
|
@ -190,7 +190,7 @@ type ImportResult struct {
|
||||||
|
|
||||||
// Sets LastTimestamp to newTime, if newTime is newer than LastTimestamp
|
// Sets LastTimestamp to newTime, if newTime is newer than LastTimestamp
|
||||||
func (i *ImportResult) UpdateTimestamp(newTime time.Time) {
|
func (i *ImportResult) UpdateTimestamp(newTime time.Time) {
|
||||||
if newTime.Unix() > i.LastTimestamp.Unix() {
|
if newTime.After(i.LastTimestamp) {
|
||||||
i.LastTimestamp = newTime
|
i.LastTimestamp = newTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ package version
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AppName = "scotty"
|
AppName = "scotty"
|
||||||
AppVersion = "0.5.0"
|
AppVersion = "0.5.2"
|
||||||
AppURL = "https://git.sr.ht/~phw/scotty/"
|
AppURL = "https://git.sr.ht/~phw/scotty/"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -247,7 +247,8 @@ func (l ScrobblerLog) rowToRecord(row []string) (Record, error) {
|
||||||
|
|
||||||
// Convert a Unix timestamp to a [time.Time] object, but treat the timestamp
|
// Convert a Unix timestamp to a [time.Time] object, but treat the timestamp
|
||||||
// as being in the given location's timezone instead of UTC.
|
// as being in the given location's timezone instead of UTC.
|
||||||
// If location is nil, the timestamp is returned as UTC.
|
// If location is nil, the timestamp is returned assumed to already be in UTC
|
||||||
|
// and returned unchanged.
|
||||||
func timeFromLocalTimestamp(timestamp int64, location *time.Location) time.Time {
|
func timeFromLocalTimestamp(timestamp int64, location *time.Location) time.Time {
|
||||||
t := time.Unix(timestamp, 0)
|
t := time.Unix(timestamp, 0)
|
||||||
|
|
||||||
|
@ -256,7 +257,7 @@ func timeFromLocalTimestamp(timestamp int64, location *time.Location) time.Time
|
||||||
if location != nil {
|
if location != nil {
|
||||||
_, offset := t.In(location).Zone()
|
_, offset := t.In(location).Zone()
|
||||||
if offset != 0 {
|
if offset != 0 {
|
||||||
t = t.Add(time.Duration(offset) * time.Second)
|
t = t.Add(-time.Duration(offset) * time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ func TestParserFallbackTimezone(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
record1 := result.Records[0]
|
record1 := result.Records[0]
|
||||||
assert.Equal(
|
assert.Equal(
|
||||||
time.Unix(1260342084, 0).Add(2*time.Hour),
|
time.Unix(1260342084, 0).Add(-2*time.Hour),
|
||||||
record1.Timestamp,
|
record1.Timestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue