ingest

package
v0.25.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 16 Imported by: 0

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

Constants

This section is empty.

Variables

View Source
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.

View Source
var ErrParserShared = errors.New("other readers follow this page and its parser still finds articles; ask your admin to rebuild 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

type AIForUser func(ctx context.Context, userID int64) (*pagefeed.Suggester, error)

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"`
	Shared bool     `json:"shared,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

type GetAI func() (*pagefeed.Suggester, error)

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

func (s *Service) Backfill(ctx context.Context, f store.Feed)

Backfill fetches full articles for a feed's newest stored entries, after its full-article switch is turned on.

func (*Service) Discover

func (s *Service) Discover(ctx context.Context, userID int64, raw string) ([]Candidate, error)

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

func (s *Service) Poll(ctx context.Context, f store.Feed)

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) Run

func (s *Service) Run(ctx context.Context)

Run polls until ctx is cancelled.

func (*Service) SeedBuiltins added in v0.8.0

func (s *Service) SeedBuiltins(ctx context.Context) error

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.

func (*Service) SubscribePage added in v0.8.0

func (s *Service) SubscribePage(ctx context.Context, userID int64, url, title string, folderID *int64) (int64, error)

SubscribePage follows a page with the server's parser for it (found or written by Discover or DiscoverAI) and polls it immediately.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL