db

package
v0.11.0 Latest Latest
Warning

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

Go to latest
Published: May 6, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Index

Constants

View Source
const (
	LibraryFeedURL  = "internal://library"
	LibraryFeedName = "Library"
)

LibraryFeedURL is the sentinel URL of the system feed that owns articles saved by the user via the Library modal (hotkey B). Excluded from user-facing lists, sync, and OPML.

Variables

This section is empty.

Functions

func IsSystemFeed added in v0.7.0

func IsSystemFeed(url string) bool

IsSystemFeed reports whether a feed is internal (e.g. Library) and should be hidden from sync, OPML export, and the Settings > Feeds list.

Types

type Article

type Article struct {
	ID           int64
	FeedID       int64
	FeedName     string // transient: populated only by cross-feed loaders
	Title        string
	URL          string
	Description  string
	Content      string
	PublishedAt  time.Time
	ReadAt       *time.Time
	StarredAt    *time.Time
	BookmarkedAt *time.Time
	CachedAt     *time.Time
	CachedBody   string
	CreatedAt    time.Time
}

type ArticleFilter

type ArticleFilter int

ArticleFilter narrows a feed's article list. Kept as a DB-level enum so callers don't pass opaque booleans or magic strings.

const (
	FilterAll ArticleFilter = iota
	FilterUnread
	FilterStarred
)

type DB

type DB struct {
	// contains filtered or unexported fields
}

func Open

func Open(path string) (*DB, error)

func (*DB) BulkMarkRead

func (d *DB) BulkMarkRead(ids []int64) error

BulkMarkRead marks many articles read in one UPDATE. No-op on empty input. Idempotent for already-read rows.

func (*DB) BulkMarkUnread

func (d *DB) BulkMarkUnread(ids []int64) error

BulkMarkUnread clears read_at on many articles in one UPDATE.

func (*DB) BulkSetBookmarked

func (d *DB) BulkSetBookmarked(ids []int64, bookmark bool) (int, error)

BulkSetBookmarked sets bookmarked_at to now() or NULL on many articles.

func (*DB) BulkSetStarred

func (d *DB) BulkSetStarred(ids []int64, starred bool) error

BulkSetStarred sets starred_at to now() or NULL on many articles.

func (*DB) CacheArticle

func (d *DB) CacheArticle(id int64, body string) error

func (*DB) Close

func (d *DB) Close() error

func (*DB) CreateFolder added in v0.11.0

func (d *DB) CreateFolder(name string) error

CreateFolder creates an empty regular folder. The folder becomes visible immediately and can later receive feeds via SetFeedCategory.

func (*DB) DeleteArticle added in v0.7.0

func (d *DB) DeleteArticle(id int64) error

DeleteArticle removes a single article by id. Used by the Library pane to discard saved URLs the user no longer wants — TrimArticles skips the system feed, so without this the table grows forever.

func (*DB) DeleteCategory

func (d *DB) DeleteCategory(name string) error

DeleteCategory empties the category of every feed that currently has it, moving them into the "Other" bucket. Thin alias around RenameCategory(name, "") that makes the caller's intent explicit.

func (*DB) DeleteFeed

func (d *DB) DeleteFeed(id int64) error

func (*DB) DeleteFolder added in v0.11.0

func (d *DB) DeleteFolder(name string) error

DeleteFolder removes the explicit folder and moves assigned feeds to Other.

func (*DB) DeleteSmartFolder

func (d *DB) DeleteSmartFolder(id int64) error

DeleteSmartFolder removes a folder by id. No-op if the id does not exist so callers don't have to pre-check.

func (*DB) GetAIEndpoint

func (d *DB) GetAIEndpoint() (string, error)

func (*DB) GetAIKey

func (d *DB) GetAIKey() (string, error)

func (*DB) GetAIModel

func (d *DB) GetAIModel() (string, error)

func (*DB) GetAIProvider

func (d *DB) GetAIProvider() (string, error)

func (*DB) GetAfterSyncCommands

func (d *DB) GetAfterSyncCommands() ([]string, error)

func (*DB) GetFeedByURL

func (d *DB) GetFeedByURL(url string) (*Feed, error)

func (*DB) GetLanguage

func (d *DB) GetLanguage() (string, error)

func (*DB) GetLibraryFeedID added in v0.7.0

func (d *DB) GetLibraryFeedID() (int64, error)

GetLibraryFeedID returns the ID of the system Library feed. Migration 007 seeds this row, so a missing row would only happen if a user deleted it manually — re-insert in that case.

func (*DB) GetReadRetentionDays added in v0.8.0

func (d *DB) GetReadRetentionDays() (int, error)

GetReadRetentionDays returns how many days read articles are kept by TrimArticles before age-based deletion. 0 means keep indefinitely (by age; max_articles_per_feed still caps the per-feed count). When the key is unset, returns defaultReadRetentionDays without writing it — we don't want a silent auto-write to obscure "never configured" from "configured to 90".

func (*DB) GetRefreshInterval

func (d *DB) GetRefreshInterval() (int, error)

func (*DB) GetSetting

func (d *DB) GetSetting(key string) (string, error)

func (*DB) GetShowImages

func (d *DB) GetShowImages() (bool, error)

func (*DB) GetShowPreview

func (d *DB) GetShowPreview() (bool, error)

GetShowPreview returns whether the inline article preview popup is enabled. Defaults to true when the setting has never been written — the feature is on-by-default so first-time users see it without hunting through settings.

func (*DB) GetSortField

func (d *DB) GetSortField() (string, error)

func (*DB) GetSortReverse

func (d *DB) GetSortReverse() (bool, error)

func (*DB) GetTheme

func (d *DB) GetTheme() (string, error)

func (*DB) InsertSmartFolder

func (d *DB) InsertSmartFolder(name, query string) (SmartFolder, error)

InsertSmartFolder appends a new folder at the end of the list. Position is computed from the current max so new folders land after existing ones.

func (*DB) LibraryUnreadCount added in v0.7.0

func (d *DB) LibraryUnreadCount() (int, error)

LibraryUnreadCount returns the number of unread saved URLs in the Library feed. Cheap enough to call on every feed-list refresh.

func (*DB) ListAllArticles

func (d *DB) ListAllArticles(limit int) ([]Article, error)

ListAllArticles returns articles across all feeds (no feed_id filter), joined with the feed name. Used by smart folders — callers then apply in-memory query filtering on the result set.

func (*DB) ListArticles

func (d *DB) ListArticles(feedID int64, limit int) ([]Article, error)

func (*DB) ListArticlesFiltered

func (d *DB) ListArticlesFiltered(feedID int64, filter ArticleFilter, limit int) ([]Article, error)

ListArticlesFiltered returns articles for a feed, narrowed by filter.

func (*DB) ListFeeds

func (d *DB) ListFeeds() ([]Feed, error)

func (*DB) ListFolders added in v0.11.0

func (d *DB) ListFolders() ([]string, error)

ListFolders returns explicit regular folders plus any non-empty feed categories that may have been created by older versions or config sync.

func (*DB) ListSmartFolders

func (d *DB) ListSmartFolders() ([]SmartFolder, error)

ListSmartFolders returns all smart folders ordered by position then id so the UI draws them in a stable, user-controlled sequence.

func (*DB) MarkFeedRead

func (d *DB) MarkFeedRead(feedID int64) (int, error)

MarkFeedRead marks every unread article in a feed as read in a single UPDATE and returns the affected row count.

func (*DB) MarkRead

func (d *DB) MarkRead(articleID int64) error

func (*DB) MarkUnread

func (d *DB) MarkUnread(articleID int64) error

MarkUnread clears the read state of a single article. Idempotent.

func (*DB) RenameCategory

func (d *DB) RenameCategory(oldName, newName string) error

RenameCategory renames one category to another across all feeds. The new name may be empty, which moves matching feeds into the "Other" bucket. No-op when no feeds match.

func (*DB) RenameFeed

func (d *DB) RenameFeed(id int64, name string) error

func (*DB) RenameFolder added in v0.11.0

func (d *DB) RenameFolder(oldName, newName string) error

RenameFolder renames the explicit folder row and all feeds assigned to the same category. Empty newName removes the explicit folder and moves assigned feeds to Other.

func (*DB) SaveLibraryURL added in v0.7.0

func (d *DB) SaveLibraryURL(libraryFeedID int64, url, placeholderTitle string) (int64, bool, error)

SaveLibraryURL inserts a saved URL into the Library feed (or updates the placeholder title on duplicate, preserving read/star/bookmark state). Returns the article ID and whether it was newly inserted. Used by the Add-URL modal: caller passes a fast placeholder title (e.g. host) and updates it later via UpdateLibraryFetched once the background readability fetch returns the real <title>.

func (*DB) SearchArticles

func (d *DB) SearchArticles(limit int) ([]SearchItem, error)

func (*DB) SetAIEndpoint

func (d *DB) SetAIEndpoint(v string) error

func (*DB) SetAIKey

func (d *DB) SetAIKey(v string) error

func (*DB) SetAIModel

func (d *DB) SetAIModel(v string) error

func (*DB) SetAIProvider

func (d *DB) SetAIProvider(v string) error

func (*DB) SetAfterSyncCommands

func (d *DB) SetAfterSyncCommands(cmds []string) error

func (*DB) SetFeedCategory

func (d *DB) SetFeedCategory(id int64, category string) error

SetFeedCategory moves a feed into (or out of) a category. Empty string means "uncategorized". Used by :categorymove command.

func (*DB) SetLanguage

func (d *DB) SetLanguage(lang string) error

func (*DB) SetReadRetentionDays added in v0.8.0

func (d *DB) SetReadRetentionDays(days int) error

SetReadRetentionDays persists the retention window (days). Passing 0 disables age-based deletion.

func (*DB) SetRefreshInterval

func (d *DB) SetRefreshInterval(minutes int) error

func (*DB) SetSetting

func (d *DB) SetSetting(key, value string) error

func (*DB) SetShowImages

func (d *DB) SetShowImages(v bool) error

func (*DB) SetShowPreview

func (d *DB) SetShowPreview(v bool) error

func (*DB) SetSortField

func (d *DB) SetSortField(v string) error

func (*DB) SetSortReverse

func (d *DB) SetSortReverse(v bool) error

func (*DB) SetTheme

func (d *DB) SetTheme(name string) error

func (*DB) ToggleBookmark

func (d *DB) ToggleBookmark(articleID int64) (bool, error)

ToggleBookmark flips the bookmarked (read-later) state of an article.

func (*DB) ToggleStar

func (d *DB) ToggleStar(articleID int64) (bool, error)

ToggleStar flips the starred state of an article: nil ↔ now(). Returns whether the article is now starred.

func (*DB) TrimArticles

func (d *DB) TrimArticles(feedID int64, max int, fetchCutoff, readCutoff time.Time) error

TrimArticles prunes old read articles in a feed once its total count exceeds max. An article is eligible for deletion only when ALL of:

  • read_at IS NOT NULL (unread is always kept)
  • starred_at IS NULL (star is an explicit user "save")
  • bookmarked_at IS NULL (read-later is an explicit user "save")
  • read_at < readCutoff (recently-read articles get a grace window so a stray `x` keystroke doesn't immediately destroy the row)
  • last_fetched_at IS NULL OR last_fetched_at < fetchCutoff (anything still in the current RSS response is protected — otherwise marking read right before a refresh would delete it and the next fetch would re-insert it as unread)

Passing a zero time.Time as readCutoff is the "retention=0 / keep everything" signal: the call returns without deleting. This matches user intent ("I want unlimited history") — the per-feed `max` cap would otherwise silently trim older read rows even when the user explicitly opted out of age-based trimming.

func (*DB) UpdateLibraryFetched added in v0.7.0

func (d *DB) UpdateLibraryFetched(id int64, title, body string) error

UpdateLibraryFetched stores the result of an async readability fetch: the extracted page title (if non-empty) replaces the placeholder, and the Markdown body is cached so the reader can show it immediately on open. Title is only overwritten when extraction succeeded — empty titles leave the placeholder intact.

func (*DB) UpdateSmartFolder

func (d *DB) UpdateSmartFolder(id int64, name, query string) error

UpdateSmartFolder overwrites the name and query of an existing folder. Position is preserved so the user's ordering survives edits.

func (*DB) UpsertArticle

func (d *DB) UpsertArticle(a Article) (bool, error)

UpsertArticle inserts or updates an article and returns whether the row was newly inserted. The pre-check is racy under concurrent writers to the same (feed_id, url): the upsert itself is atomic, so rows stay consistent, but the inserted flag may be off — fetcher loops are per-feed serial so this is dormant in practice.

func (*DB) UpsertFeed

func (d *DB) UpsertFeed(name, url, category string) (Feed, error)

UpsertFeed inserts or updates a feed by URL. Category is overwritten on conflict so yaml edits take effect on next sync.

type Feed

type Feed struct {
	ID          int64
	Name        string
	URL         string
	Category    string
	Position    int
	CreatedAt   time.Time
	UnreadCount int
}

type SearchItem

type SearchItem struct {
	ArticleID    int64
	FeedID       int64
	FeedName     string
	Title        string
	URL          string
	Description  string
	CachedBody   string
	PublishedAt  time.Time
	ReadAt       *time.Time
	StarredAt    *time.Time
	BookmarkedAt *time.Time
}

type SmartFolder

type SmartFolder struct {
	ID       int64
	Name     string
	Query    string
	Position int
}

SmartFolder is a saved query that appears as a virtual folder in the feed list. Selecting it loads articles from across all feeds matching Query (using the rdr query language; see internal/ui/query.go).

Jump to

Keyboard shortcuts

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