fix(favorites): use cursor-based pagination instead of page numbers
FA's /favorites/{user}/ pagination is cursor-addressed by the fave-ID
of the last item on the previous page (e.g.
/favorites/{user}/1951234825/next), not by sequential integers. The
previous URL builder generated /favorites/{user}/{N}/ for N>=2; FA
interpreted that as a malformed cursor and silently returned page 1,
which caused the Favorites iterator to loop forever and the new
FavoritesPage to report HasNext=true on every call.
Changes:
- urls.Favorites(name) returns the first-page URL; new
urls.FavoritesCursor(name, cursor) builds /favorites/.../next URLs.
- FavoritesPage now takes a cursor string; empty = first page.
Returns ListingPage.NextPage as the opaque fave-ID for the next call.
- ListingPage gains NextPage string (decimal page number for
Gallery/Scraps, fave-ID cursor for Favorites) and drops the Page int
field that conflated those two notions.
- Client.Favorites iterator now walks cursors internally; StartPage
is ignored for favorites (documented).
- detectNextPage / nextPageURL now parse the form action so the same
helper works for both page-number and cursor pagination.
- Added regression test that fails on the infinite-loop bug.
- Example: examples/favorites_page demonstrates cursor walking.
This commit is contained in:
@@ -19,6 +19,15 @@ import (
|
||||
// pure HTML the same behaviour as before [WithExperimentalJSONListings]
|
||||
// existed.
|
||||
func parseGalleryPage(doc *goquery.Document, useJSON bool) (items []*Submission, hasNext bool) {
|
||||
items, _, hasNext = parseListingPage(doc, useJSON)
|
||||
return items, hasNext
|
||||
}
|
||||
|
||||
// parseListingPage parses one page of a listing endpoint and also returns
|
||||
// the raw next-page URL FA emits in its "Next" pagination form. Callers
|
||||
// that need to chain across cursor-based pages (Favorites) consume the
|
||||
// URL; callers that don't (Gallery / Scraps) can ignore it.
|
||||
func parseListingPage(doc *goquery.Document, useJSON bool) (items []*Submission, nextURL string, hasNext bool) {
|
||||
var jsonData listingJSONMap
|
||||
if useJSON {
|
||||
jsonData = readListingJSON(doc)
|
||||
@@ -28,8 +37,8 @@ func parseGalleryPage(doc *goquery.Document, useJSON bool) (items []*Submission,
|
||||
items = append(items, s)
|
||||
}
|
||||
})
|
||||
hasNext = detectNextPage(doc)
|
||||
return items, hasNext
|
||||
nextURL, hasNext = nextPageURL(doc)
|
||||
return items, nextURL, hasNext
|
||||
}
|
||||
|
||||
// parseGalleryFigure lifts a single submission preview from a
|
||||
|
||||
Reference in New Issue
Block a user