mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-06 21:36:37 +08:00
bug处理
This commit is contained in:
@@ -89,7 +89,7 @@ func listLibrarySeriesHandler(svc *service.Container) gin.HandlerFunc {
|
|||||||
writeInternalOrCanceled(c, err)
|
writeInternalOrCanceled(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cards = service.SortSeriesCards(cards, sortSpec.Field, sortSpec.Order, history)
|
cards = sortRemoteSeriesCards(cards, sortSpec, history)
|
||||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||||
size, _ := strconv.Atoi(c.DefaultQuery("page_size", "500"))
|
size, _ := strconv.Atoi(c.DefaultQuery("page_size", "500"))
|
||||||
if page < 1 {
|
if page < 1 {
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"slices"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/truewhile/MeBox/internal/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
// sortRemoteSeriesCards keeps the DateLastContentAdded order returned by the
|
||||||
|
// remote Emby server when LastAddedAt is not exposed in the Series DTO.
|
||||||
|
func sortRemoteSeriesCards(cards []service.SeriesCard, spec service.MediaSortSpec, history map[string]time.Time) []service.SeriesCard {
|
||||||
|
if spec.Field != "updated_at" {
|
||||||
|
return service.SortSeriesCards(cards, spec.Field, spec.Order, history)
|
||||||
|
}
|
||||||
|
|
||||||
|
out := append([]service.SeriesCard(nil), cards...)
|
||||||
|
// RemoteSeriesCards always fetches DateLastContentAdded in descending order.
|
||||||
|
if spec.Order == "asc" {
|
||||||
|
slices.Reverse(out)
|
||||||
|
}
|
||||||
|
return service.SortSeriesCards(out, spec.Field, spec.Order, history)
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/truewhile/MeBox/internal/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSortRemoteSeriesCardsUpdatedAtUsesRemoteOrder(t *testing.T) {
|
||||||
|
cards := []service.SeriesCard{{Key: "newest"}, {Key: "middle"}, {Key: "oldest"}}
|
||||||
|
|
||||||
|
desc := sortRemoteSeriesCards(cards, service.MediaSortSpec{Field: "updated_at", Order: "desc"}, nil)
|
||||||
|
if desc[0].Key != "newest" || desc[1].Key != "middle" || desc[2].Key != "oldest" {
|
||||||
|
t.Fatalf("descending order = %q, %q, %q", desc[0].Key, desc[1].Key, desc[2].Key)
|
||||||
|
}
|
||||||
|
|
||||||
|
asc := sortRemoteSeriesCards(cards, service.MediaSortSpec{Field: "updated_at", Order: "asc"}, nil)
|
||||||
|
if asc[0].Key != "oldest" || asc[1].Key != "middle" || asc[2].Key != "newest" {
|
||||||
|
t.Fatalf("ascending order = %q, %q, %q", asc[0].Key, asc[1].Key, asc[2].Key)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,7 +70,9 @@ func SortSeriesCards(cards []SeriesCard, field, order string, history map[string
|
|||||||
}
|
}
|
||||||
sort.SliceStable(out, func(i, j int) bool {
|
sort.SliceStable(out, func(i, j int) bool {
|
||||||
cmp := compareSeriesByField(out[i], out[j], spec, history)
|
cmp := compareSeriesByField(out[i], out[j], spec, history)
|
||||||
if cmp == 0 {
|
// updated_at 表示最后一集添加日期。远程卡片可能没有该字段,此时
|
||||||
|
// 保持调用方给定的顺序,不要用 ID 再次打乱。
|
||||||
|
if cmp == 0 && spec.Field != "updated_at" {
|
||||||
cmp = compareID(out[i].Key, out[j].Key)
|
cmp = compareID(out[i].Key, out[j].Key)
|
||||||
}
|
}
|
||||||
return cmp < 0
|
return cmp < 0
|
||||||
@@ -173,7 +175,7 @@ func seriesUpdatedTime(card SeriesCard) (time.Time, bool) {
|
|||||||
if card.LastAddedAt != nil && !card.LastAddedAt.IsZero() {
|
if card.LastAddedAt != nil && !card.LastAddedAt.IsZero() {
|
||||||
return *card.LastAddedAt, true
|
return *card.LastAddedAt, true
|
||||||
}
|
}
|
||||||
return mediaUpdatedTime(card.Rep)
|
return time.Time{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func seriesLastPlayed(card SeriesCard, history map[string]time.Time) (time.Time, bool) {
|
func seriesLastPlayed(card SeriesCard, history map[string]time.Time) (time.Time, bool) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/truewhile/MeBox/internal/model"
|
"github.com/truewhile/MeBox/internal/model"
|
||||||
)
|
)
|
||||||
@@ -40,3 +41,45 @@ func TestSortSeriesCardsTitleAsc(t *testing.T) {
|
|||||||
t.Fatalf("series order = %q, %q", got[0].Key, got[1].Key)
|
t.Fatalf("series order = %q, %q", got[0].Key, got[1].Key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSortSeriesCardsUpdatedAtDoesNotFallbackToMediaDate(t *testing.T) {
|
||||||
|
olderMediaDate := time.Date(2023, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
newerMediaDate := time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
cards := []SeriesCard{
|
||||||
|
{
|
||||||
|
Key: "remote-first",
|
||||||
|
Rep: model.Media{Base: model.Base{
|
||||||
|
ID: "remote-first",
|
||||||
|
CreatedAt: olderMediaDate,
|
||||||
|
UpdatedAt: olderMediaDate,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "remote-second",
|
||||||
|
Rep: model.Media{Base: model.Base{
|
||||||
|
ID: "remote-second",
|
||||||
|
CreatedAt: newerMediaDate,
|
||||||
|
UpdatedAt: newerMediaDate,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
got := SortSeriesCards(cards, "updated_at", "desc", nil)
|
||||||
|
if got[0].Key != "remote-first" || got[1].Key != "remote-second" {
|
||||||
|
t.Fatalf("series order = %q, %q, want remote-provided order", got[0].Key, got[1].Key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSortSeriesCardsUpdatedAtSortsKnownLastEpisodeDates(t *testing.T) {
|
||||||
|
older := time.Date(2024, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
newer := time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
cards := []SeriesCard{
|
||||||
|
{Key: "older", LastAddedAt: &older},
|
||||||
|
{Key: "newer", LastAddedAt: &newer},
|
||||||
|
}
|
||||||
|
|
||||||
|
got := SortSeriesCards(cards, "updated_at", "desc", nil)
|
||||||
|
if got[0].Key != "newer" || got[1].Key != "older" {
|
||||||
|
t.Fatalf("series order = %q, %q", got[0].Key, got[1].Key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -460,7 +460,7 @@ export function groupSeries(items: Media[] = []): SeriesCard[] {
|
|||||||
? compactSeriesKey(externalKey)
|
? compactSeriesKey(externalKey)
|
||||||
: getSeriesKey(m)
|
: getSeriesKey(m)
|
||||||
|
|
||||||
const mAddedAt = m.created_at || m.updated_at || ''
|
const mAddedAt = m.updated_at || m.created_at || ''
|
||||||
const g = groups.get(key)
|
const g = groups.get(key)
|
||||||
if (!g) {
|
if (!g) {
|
||||||
groups.set(key, { key, rep: m, linkMedia: m, count: 1, last_added_at: mAddedAt })
|
groups.set(key, { key, rep: m, linkMedia: m, count: 1, last_added_at: mAddedAt })
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ export function sortMediaList(
|
|||||||
case 'created_at':
|
case 'created_at':
|
||||||
return compareDates(a.created_at, b.created_at, order) || compareStrings(a.title, b.title, 'asc')
|
return compareDates(a.created_at, b.created_at, order) || compareStrings(a.title, b.title, 'asc')
|
||||||
case 'updated_at':
|
case 'updated_at':
|
||||||
return compareDates(a.created_at || a.updated_at, b.created_at || b.updated_at, order) || compareStrings(a.title, b.title, 'asc')
|
return compareDates(a.updated_at || a.created_at, b.updated_at || b.created_at, order) || compareStrings(a.title, b.title, 'asc')
|
||||||
case 'rating':
|
case 'rating':
|
||||||
case 'imdb_rating': {
|
case 'imdb_rating': {
|
||||||
const cmp = compareNumbers(a.rating || 0, b.rating || 0, order)
|
const cmp = compareNumbers(a.rating || 0, b.rating || 0, order)
|
||||||
|
|||||||
Reference in New Issue
Block a user