f2151309f7
Extract gate, route, fetch and both parses into readSeriesPage, which returns facts only; checkOne and acquire keep their scheduling, stamp order and persistence policies. The poller also stops logging the fetched body length, which only made sense while the body lived at the call site.
56 lines
2.1 KiB
Go
56 lines
2.1 KiB
Go
package latest
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
// seriesRead carries the two facts the poll and the acquirer both extract
|
|
// from a series page. Persistence, stamps and scheduling stay with the
|
|
// callers, so the policies that keep the two flows distinct (stamp order,
|
|
// cooldowns) are not swallowed by the module.
|
|
type seriesRead struct {
|
|
Latest latestChapter
|
|
HasLatest bool
|
|
Cover string
|
|
HasCover bool
|
|
}
|
|
|
|
// errNotFetchable and errNoFetcher separate the gate and the route from fetch
|
|
// failures so each caller keeps its own distinct log line for all three.
|
|
var (
|
|
errNotFetchable = errors.New("series url not fetchable")
|
|
errNoFetcher = errors.New("no fetcher for site")
|
|
)
|
|
|
|
// readSeriesPage performs the series-page read the poll and the acquirer have
|
|
// in common: gate the address, choose the route, fetch the page, extract the
|
|
// Latest Chapter and the Cover address. It persists nothing and stamps
|
|
// nothing.
|
|
//
|
|
// series_url arrives in a client-supplied PUT body (PUT /bookmarks/{key}
|
|
// accepts any string), so the gate is not an optimisation against burning a
|
|
// request on an unknown site: without it, the server would issue a GET from
|
|
// its own network position to whatever URL a token-holder writes, including
|
|
// link-local/internal addresses or non-https schemes.
|
|
func readSeriesPage(ctx context.Context, site, seriesURL string, browser, tls Fetcher) (seriesRead, error) {
|
|
if !fetchableSeriesURL(site, seriesURL) {
|
|
return seriesRead{}, fmt.Errorf("%w: site=%q url=%q", errNotFetchable, site, seriesURL)
|
|
}
|
|
f := fetcherFor(site, browser, tls)
|
|
if f == nil {
|
|
return seriesRead{}, fmt.Errorf("%w: site %q", errNoFetcher, site)
|
|
}
|
|
body, status, err := f.Get(ctx, seriesURL)
|
|
if err != nil {
|
|
return seriesRead{}, fmt.Errorf("fetch %s: %w", seriesURL, err)
|
|
}
|
|
if status != 200 {
|
|
return seriesRead{}, fmt.Errorf("fetch %s: status %d", seriesURL, status)
|
|
}
|
|
latest, hasLatest := latestChapterFrom(site, seriesURL, body)
|
|
cover, hasCover := coverFrom(site, seriesURL, body)
|
|
return seriesRead{Latest: latest, HasLatest: hasLatest, Cover: cover, HasCover: hasCover}, nil
|
|
}
|