Documentation
¶
Overview ¶
Package ingest polls due feeds, stores new entries, and subscribes to new feeds (with discovery from HTML pages). It is the only writer of feed content; a single in-process scheduler replaces a job queue because there is exactly one application replica.
Index ¶
- Variables
- type AIForUser
- type Candidate
- type GetAI
- type Service
- func (s *Service) Backfill(ctx context.Context, f store.Feed)
- func (s *Service) Discover(ctx context.Context, userID int64, raw string) ([]Candidate, error)
- func (s *Service) DiscoverAI(ctx context.Context, userID int64, raw string, getAI GetAI, ...) (Candidate, error)
- func (s *Service) FullArticle(ctx context.Context, userID int64, e store.Entry) (*extract.Result, error)
- func (s *Service) Poll(ctx context.Context, f store.Feed)
- func (s *Service) Rebuild(ctx context.Context, userID int64, raw string, getAI GetAI, force bool) (Candidate, error)
- func (s *Service) Run(ctx context.Context)
- func (s *Service) SeedBuiltins(ctx context.Context) error
- func (s *Service) Subscribe(ctx context.Context, userID int64, url, title string, folderID *int64) (int64, error)
- func (s *Service) SubscribeAuto(ctx context.Context, userID int64, raw, title string, folderID *int64) (*store.Feed, error)
- func (s *Service) SubscribePage(ctx context.Context, userID int64, url, title string, folderID *int64) (int64, error)
Constants ¶
This section is empty.
Variables ¶
var ErrNoFeed = errors.New("no feed found at that address")
ErrNoFeed means a site has no feed and no article list the exact methods or an existing parser can read; an AI may still write a parser for it.
ErrParserShared refuses a reader's rebuild of a parser that still reads its page and that other readers follow: it would change their feeds too.
Functions ¶
This section is empty.
Types ¶
type AIForUser ¶ added in v0.8.0
AIForUser returns the reader's AI client, or an error explaining why there is none (no key saved, daily limit reached).
type Candidate ¶
type Candidate struct {
URL string `json:"url"`
Title string `json:"title"`
Description string `json:"description"`
SiteURL string `json:"siteUrl"`
IconURL string `json:"iconUrl"`
ItemCount int `json:"itemCount"`
LatestAt int64 `json:"latestAt"`
// Page candidates are web pages with no feed, read by a parser: Method
// says how it finds the articles, Shared that the server already had it
// (written for another reader), Sample shows a few titles.
Page bool `json:"page,omitempty"`
Method string `json:"method,omitempty"`
Sample []string `json:"sample,omitempty"`
// contains filtered or unexported fields
}
Candidate is a feed found while resolving a URL to subscribe to.
type GetAI ¶ added in v0.8.0
GetAI returns the reader's AI client; it is only called when a parser must be written, so the AI is never asked about a page twice.
type Service ¶
type Service struct {
Store *store.Store
Fetch *fetch.Client
// Extract fetches full articles for feeds that publish only summaries.
Extract *extract.Extractor
// AIFor gives a reader's own AI client, for pages with no feed added by
// apps (SubscribeAuto). Nil leaves AI to the web app.
AIFor AIForUser
Log *slog.Logger
Concurrency int
Tick time.Duration
// Jev, when the admin has given a TypeSafe key, finds the website
// material the rules leave at articles' ends (see dropMaterial).
Jev *typesafe.Client
// Notify is called after new entries arrive for a user (for live UI updates).
Notify func(userID int64)
// OnNewEntries is called (in its own goroutine) after a poll inserted
// entries, with the crawl ID they are all above; used for notifications.
OnNewEntries func(ctx context.Context, f store.Feed, since int64)
// RetentionDays deletes read, unstarred articles older than this that
// have left their feed. Zero keeps everything (the default).
RetentionDays int
// contains filtered or unexported fields
}
func (*Service) Backfill ¶ added in v0.6.0
Backfill fetches full articles for a feed's newest stored entries, after its full-article switch is turned on.
func (*Service) Discover ¶
Discover resolves a site or feed URL to the feeds it offers. A site with no feed is read as a page feed: by the parser the server already has for it, or by one worked out exactly and saved for every reader. An article's address leads to the listing above it.
func (*Service) DiscoverAI ¶ added in v0.8.0
func (s *Service) DiscoverAI(ctx context.Context, userID int64, raw string, getAI GetAI, rebuild, force bool) (Candidate, error)
DiscoverAI finds a parser for a page with no feed, writing one with the reader's AI only when the server has none that still reads the page (or rebuild is set). The AI's parser is saved for every reader. A rebuild replaces a working parser others follow only when force is set (admins).
func (*Service) FullArticle ¶ added in v0.6.0
func (s *Service) FullArticle(ctx context.Context, userID int64, e store.Entry) (*extract.Result, error)
FullArticle fetches one entry's full article and stores it, or records why it couldn't. A reader asked for it, so it replaces the feed's text whatever that is.
func (*Service) Poll ¶
Poll fetches one feed and records the result. Safe to call concurrently; overlapping polls of the same feed are skipped.
func (*Service) Rebuild ¶ added in v0.8.0
func (s *Service) Rebuild(ctx context.Context, userID int64, raw string, getAI GetAI, force bool) (Candidate, error)
Rebuild writes a new parser for a page whose parser stopped reading it: exactly if the page allows, else with the reader's AI. Every reader of the page gets the new parser, so a reader can't replace one that still works for others; an admin can (force).
func (*Service) SeedBuiltins ¶ added in v0.8.0
SeedBuiltins installs the parsers shipped with the app.
func (*Service) Subscribe ¶
func (s *Service) Subscribe(ctx context.Context, userID int64, url, title string, folderID *int64) (int64, error)
Subscribe adds a feed for the user and polls it immediately.
func (*Service) SubscribeAuto ¶ added in v0.8.0
func (s *Service) SubscribeAuto(ctx context.Context, userID int64, raw, title string, folderID *int64) (*store.Feed, error)
SubscribeAuto subscribes to whatever an address offers, choosing for the reader, for apps (Reeder) that can only send an address: its feed if it has one; else its article list read exactly; else, when the reader has set up AI, the list as the AI reads it. folderID may be nil.