// Package domain contains the core value types shared across all packages // in this module. It has zero internal imports — only the standard library. // Every other package imports domain; domain imports nothing from this module. package domain import "time" // ── Book types ──────────────────────────────────────────────────────────────── // BookMeta carries all bibliographic information about a novel. type BookMeta struct { Slug string `json:"slug"` Title string `json:"title"` Author string `json:"author"` Cover string `json:"cover,omitempty"` Status string `json:"status,omitempty"` Genres []string `json:"genres,omitempty"` Summary string `json:"summary,omitempty"` TotalChapters int `json:"total_chapters,omitempty"` SourceURL string `json:"source_url"` Ranking int `json:"ranking,omitempty"` Rating float64 `json:"rating,omitempty"` } // CatalogueEntry is a lightweight book reference returned by catalogue pages. type CatalogueEntry struct { Title string `json:"title"` URL string `json:"url"` } // ChapterRef is a reference to a single chapter returned by chapter-list pages. type ChapterRef struct { Number int `json:"number"` Title string `json:"title"` URL string `json:"url"` Volume int `json:"volume,omitempty"` } // Chapter contains the fully-extracted text of a single chapter. type Chapter struct { Ref ChapterRef `json:"ref"` Text string `json:"text"` } // RankingItem represents a single entry in the novel ranking list. type RankingItem struct { Rank int `json:"rank"` Slug string `json:"slug"` Title string `json:"title"` Author string `json:"author,omitempty"` Cover string `json:"cover,omitempty"` Status string `json:"status,omitempty"` Genres []string `json:"genres,omitempty"` SourceURL string `json:"source_url,omitempty"` Updated time.Time `json:"updated,omitempty"` } // ── Storage record types ────────────────────────────────────────────────────── // ChapterInfo is a lightweight chapter descriptor stored in the index. type ChapterInfo struct { Number int `json:"number"` Title string `json:"title"` Date string `json:"date,omitempty"` } // ReadingProgress holds a single user's reading position for one book. type ReadingProgress struct { Slug string `json:"slug"` Chapter int `json:"chapter"` UpdatedAt time.Time `json:"updated_at"` } // ── Task record types ───────────────────────────────────────────────────────── // TaskStatus enumerates the lifecycle states of any task. type TaskStatus string const ( TaskStatusPending TaskStatus = "pending" TaskStatusRunning TaskStatus = "running" TaskStatusDone TaskStatus = "done" TaskStatusFailed TaskStatus = "failed" TaskStatusCancelled TaskStatus = "cancelled" ) // ScrapeTask represents a book-scraping job stored in PocketBase. type ScrapeTask struct { ID string `json:"id"` Kind string `json:"kind"` // "catalogue" | "book" | "book_range" TargetURL string `json:"target_url"` // non-empty for single-book tasks FromChapter int `json:"from_chapter,omitempty"` ToChapter int `json:"to_chapter,omitempty"` WorkerID string `json:"worker_id,omitempty"` Status TaskStatus `json:"status"` BooksFound int `json:"books_found"` ChaptersScraped int `json:"chapters_scraped"` ChaptersSkipped int `json:"chapters_skipped"` Errors int `json:"errors"` Started time.Time `json:"started"` Finished time.Time `json:"finished,omitempty"` ErrorMessage string `json:"error_message,omitempty"` } // ScrapeResult is the outcome reported by the runner after finishing a ScrapeTask. type ScrapeResult struct { BooksFound int `json:"books_found"` ChaptersScraped int `json:"chapters_scraped"` ChaptersSkipped int `json:"chapters_skipped"` Errors int `json:"errors"` ErrorMessage string `json:"error_message,omitempty"` } // AudioTask represents an audio-generation job stored in PocketBase. type AudioTask struct { ID string `json:"id"` CacheKey string `json:"cache_key"` // "slug/chapter/voice" Slug string `json:"slug"` Chapter int `json:"chapter"` Voice string `json:"voice"` WorkerID string `json:"worker_id,omitempty"` Status TaskStatus `json:"status"` ErrorMessage string `json:"error_message,omitempty"` Started time.Time `json:"started"` Finished time.Time `json:"finished,omitempty"` } // AudioResult is the outcome reported by the runner after finishing an AudioTask. type AudioResult struct { ObjectKey string `json:"object_key,omitempty"` ErrorMessage string `json:"error_message,omitempty"` }