app

package
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: Oct 4, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrCacheRefresh = errors.New("book updated on Hardcover but the local cache could not be refreshed; run `oku sync`")

ErrCacheRefresh reports that a write reached Hardcover but the local cache could not be refreshed afterwards. The remote change stands, so callers should report success and warn rather than fail. The message is user-facing: the TUI renders err.Error() verbatim.

Functions

func SortQueue added in v0.10.0

func SortQueue(books []model.UserBook, ids []int)

func WriteExport added in v0.10.0

func WriteExport(w io.Writer, data LibraryExport, format string) error

Types

type App

type App struct {
	API    *api.Client
	Store  *store.Store
	Config config.Config
}

App is the core engine that orchestrates the API client and local store.

func New

func New(apiClient *api.Client, db *store.Store, cfg config.Config) *App

New creates a new App instance.

func (*App) AddActiveBook

func (a *App) AddActiveBook(bookID int) error

AddActiveBook appends a book to the active list if missing.

func (*App) AddJournalEntry added in v0.10.0

func (a *App) AddJournalEntry(ctx context.Context, bookID int, event, text string) (int, error)

func (*App) CachedQueueOrder added in v0.10.0

func (a *App) CachedQueueOrder() ([]int, error)

func (*App) ChangeStatus

func (a *App) ChangeStatus(ctx context.Context, bookID int, status model.Status) error

ChangeStatus changes a book's status. If bookID is 0, uses the single active book. If the book has no user_book entry yet, creates one via InsertUserBook.

func (*App) ExportBooks added in v0.10.0

func (a *App) ExportBooks(ctx context.Context) (LibraryExport, error)

func (*App) GetActiveBookID

func (a *App) GetActiveBookID() (int, error)

GetActiveBookID returns the active book ID from local state. When multiple active books exist, callers must pass --book explicitly.

func (*App) GetActiveBookIDs

func (a *App) GetActiveBookIDs() ([]int, error)

GetActiveBookIDs returns the list of active reading book IDs.

func (*App) GetActiveBooks

func (a *App) GetActiveBooks() ([]model.UserBook, error)

GetActiveBooks returns all active books found in cache.

func (*App) GetBookDetail added in v0.10.0

func (a *App) GetBookDetail(ctx context.Context, id int, refresh bool) (*api.BookDetail, error)

func (*App) GetHeatmap

func (a *App) GetHeatmap(weeks int) ([]model.DayActivity, error)

GetHeatmap returns daily activity data for the given number of weeks, merging timer minutes with Hardcover reading-journal days (progress updates, finished books) so the heatmap matches the hardcover.app one.

func (*App) GetReadingStats added in v0.6.0

func (a *App) GetReadingStats() (*model.ReadingStats, error)

GetReadingStats assembles everything the stats view displays from the local cache. It never performs a network request; run a sync first for fresh data.

func (*App) GetUserBookForTitle added in v0.4.1

func (a *App) GetUserBookForTitle(title string) (*model.UserBook, error)

GetUserBookForTitle returns a single cached user book by title match. It prefers exact case-insensitive matches, then substring matches. Returns nil when there is no unambiguous match.

func (*App) ImportBooks added in v0.10.0

func (a *App) ImportBooks(ctx context.Context, rows []TransferBook, apply bool) ([]ImportResult, error)

ImportBooks previews by default. Existing books are always skipped, preserving ratings, progress and reviews. A failed partially-added row is explicitly reported.

func (*App) LastSyncAt added in v0.9.0

func (a *App) LastSyncAt() time.Time

LastSyncAt is when the library was last synced with Hardcover: the newest of the per-status stamps, or the zero time when it never was.

func (*App) ListAllCachedUserBooks added in v0.7.0

func (a *App) ListAllCachedUserBooks() ([]model.UserBook, error)

ListAllCachedUserBooks returns every cached user book across all statuses, de-duplicated by book ID.

func (*App) ListBooks

func (a *App) ListBooks(ctx context.Context, status model.Status, refresh bool) ([]model.UserBook, error)

ListBooks returns user books for the given status. Serves from cache by default; if refresh is true, fetches from API first.

func (*App) ListCachedBooks added in v0.4.3

func (a *App) ListCachedBooks(status model.Status) ([]model.UserBook, bool, error)

ListCachedBooks returns locally cached books and reports whether the cache should be refreshed. It never performs a network request.

func (*App) MoveQueueBook added in v0.10.0

func (a *App) MoveQueueBook(ctx context.Context, bookID, delta int) ([]int, error)

MoveQueueBook updates one adjacent pair. Missing shelf books are appended to the private ranked list; reading status remains independent of priority.

func (*App) RateBook added in v0.4.1

func (a *App) RateBook(ctx context.Context, bookID int, rating float64) error

RateBook updates a rating for a book in the user's library.

func (*App) RefreshQueue added in v0.10.0

func (a *App) RefreshQueue(ctx context.Context) ([]int, error)

func (*App) RemoveActiveBook

func (a *App) RemoveActiveBook(bookID int) error

RemoveActiveBook removes a book from the active list.

func (*App) ResolveBookID

func (a *App) ResolveBookID(bookID int) (int, error)

ResolveBookID returns the given bookID if > 0, otherwise the active book ID.

func (*App) ReviewBook added in v0.4.1

func (a *App) ReviewBook(ctx context.Context, bookID int, rating float64, review string) error

ReviewBook updates both rating and review text for a book in the user's library.

func (*App) SearchBooks

func (a *App) SearchBooks(ctx context.Context, query string, limit int, mode model.SearchMode) ([]model.SearchResult, error)

SearchBooks queries the Hardcover API for books matching the query and mode. Search always hits the API (not cache) since it uses Typesense.

func (*App) SyncAll

func (a *App) SyncAll(ctx context.Context) error

SyncAll refreshes all tracked status lists into the local cache.

func (*App) SyncStats added in v0.6.0

func (a *App) SyncStats(ctx context.Context) error

SyncStats refreshes the journal and goal caches from the API. Journal history is limited to what the heatmap can show plus margin.

func (*App) TimerList

func (a *App) TimerList(limit int) ([]model.ReadingSession, error)

TimerList returns the most recent reading sessions.

func (*App) TimerStart

func (a *App) TimerStart(bookID int) error

TimerStart begins a new reading session for the given book. Returns an error if a timer is already running.

func (*App) TimerStats

func (a *App) TimerStats(weeks int) (model.WeeklyStats, error)

TimerStats returns weekly reading stats for the given number of weeks back from now.

func (*App) TimerStatus

func (a *App) TimerStatus() (*model.TimerState, error)

TimerStatus returns the current timer state, or nil if no timer is running.

func (*App) TimerStop

func (a *App) TimerStop() (*model.ReadingSession, error)

TimerStop ends the current timer, records the session, and returns it. Returns an error if no timer is running.

func (*App) TrendingBooks added in v0.10.0

func (a *App) TrendingBooks(ctx context.Context, period string, limit int) ([]model.SearchResult, error)

func (*App) UpdateProgress

func (a *App) UpdateProgress(ctx context.Context, bookID int, pageUpdate model.PageUpdate) (int, error)

UpdateProgress updates the reading progress for a book. If bookID is 0, uses the single active book.

func (*App) ValidateToken

func (a *App) ValidateToken(ctx context.Context) (int, string, error)

ValidateToken calls GetMe to verify the token works and caches the user ID.

type ImportResult added in v0.10.0

type ImportResult struct {
	Title  string `json:"title"`
	BookID int    `json:"book_id"`
	Action string `json:"action"`
	Detail string `json:"detail,omitempty"`
}

type LibraryExport added in v0.10.0

type LibraryExport struct {
	Version int            `json:"version"`
	Books   []TransferBook `json:"books"`
}

type TransferBook added in v0.10.0

type TransferBook struct {
	BookID     int                   `json:"book_id"`
	ISBN       string                `json:"isbn,omitempty"`
	Title      string                `json:"title"`
	Status     string                `json:"status"`
	Rating     float64               `json:"rating"`
	Review     string                `json:"review,omitempty"`
	ReviewedAt string                `json:"reviewed_at,omitempty"`
	Reads      []api.APIUserBookRead `json:"reads,omitempty"`
}

TransferBook is a portable library row. IDs are Hardcover IDs, never Goodreads IDs.

func ReadImport added in v0.10.0

func ReadImport(r io.Reader, format string) ([]TransferBook, error)

Jump to

Keyboard shortcuts

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