Documentation
¶
Overview ¶
Package booksource implements a Go reader for Legado-compatible source definitions.
Index ¶
- Variables
- func LoadCachedContent(dataDir string, book Book, chapter Chapter) (string, error)
- func MatchAlternativeChapter(chapters []Chapter, previousTitle string, previousIndex int) (index int, matched bool)
- func NormalizeContent(text string) string
- func SaveCachedChapters(dataDir string, book Book, chapters []Chapter) error
- func SaveCachedContent(dataDir string, book Book, chapter Chapter, content string) error
- func SaveSources(dataDir string, sources []Source) error
- func SourceDefinitionFingerprint(source Source) string
- func SourceGroups(source Source) []string
- func SourceKey(source Source) string
- func ValidateSource(source Source) error
- type AlternativeResult
- type Book
- type BookRule
- type Chapter
- type Client
- func (c *Client) BookInfo(ctx context.Context, source Source, book Book) (Book, error)
- func (c *Client) Chapters(ctx context.Context, source Source, book Book) ([]Chapter, error)
- func (c *Client) CheckSource(ctx context.Context, source Source, keyword string, deep bool) (result SourceCheckResult)
- func (c *Client) Content(ctx context.Context, source Source, book Book, chapter Chapter) (string, error)
- func (c *Client) FindAlternatives(ctx context.Context, sources []Source, current Book, page int) (AlternativeResult, error)
- func (c *Client) Import(ctx context.Context, location string) ([]Source, error)
- func (c *Client) IsLoggedIn(src Source) bool
- func (c *Client) LoadSessions(dir string) error
- func (c *Client) Login(ctx context.Context, src Source, fields map[string]string) error
- func (c *Client) LoginStatus(src Source) bool
- func (c *Client) Logout(src Source) error
- func (c *Client) SaveSessions(dir string) error
- func (c *Client) Search(ctx context.Context, source Source, keyword string, page int) ([]Book, error)
- type ContentRule
- type Evaluator
- func (e *Evaluator) Elements(input any, rule string) ([]any, error)
- func (e *Evaluator) EvalJS(code string, result any) (output any, evalErr error)
- func (e *Evaluator) SetJSBindings(bindings map[string]any) *Evaluator
- func (e *Evaluator) SetJSContext(ctx context.Context) *Evaluator
- func (e *Evaluator) SetJSLib(code string) *Evaluator
- func (e *Evaluator) SetJSTimeout(timeout time.Duration) *Evaluator
- func (e *Evaluator) String(input any, rule string) (string, error)
- func (e *Evaluator) Strings(input any, rule string) ([]string, error)
- type ImportPreview
- type LoginField
- type Source
- func ApplyImport(existing []Source, preview ImportPreview, selected map[string]bool, ...) []Source
- func CloneSources(sources []Source) []Source
- func Import(ctx context.Context, location string) ([]Source, error)
- func LoadSources(dataDir string) ([]Source, error)
- func MergeSources(existing, incoming []Source) []Source
- func RemoveCollection(sources []Source, id string) (remaining []Source, removed int, shared int)
- type SourceCheckResult
- type SourceCollection
- type SourceManagement
- type TOCRule
Constants ¶
This section is empty.
Variables ¶
var ErrJSTimeout = errors.New("JavaScript执行超时")
Functions ¶
func LoadCachedContent ¶
func MatchAlternativeChapter ¶
func MatchAlternativeChapter(chapters []Chapter, previousTitle string, previousIndex int) (index int, matched bool)
MatchAlternativeChapter uses only unique matches. When no reliable title or chapter number exists, the caller must disclose that the clamped index is an approximation rather than an identified chapter.
func NormalizeContent ¶
NormalizeContent converts common HTML fragments to readable chapter text. Unknown angle-bracket words are preserved; this is not an HTML sanitizer. Entity decoding is bounded to three layers for escaped source responses.
func SaveCachedChapters ¶
func SaveCachedContent ¶
func SaveSources ¶
func SourceDefinitionFingerprint ¶
Personal preferences and display names do not change the rules being checked.
func SourceGroups ¶
func ValidateSource ¶
Types ¶
type AlternativeResult ¶
AlternativeResult retains successful candidates when individual sources fail.
type Book ¶
type Book struct {
Variables map[string]any `json:"variables,omitempty"`
SourceURL string `json:"source_url"`
SourceName string `json:"source_name"`
URL string `json:"url"`
TOCURL string `json:"toc_url,omitempty"`
Name string `json:"name"`
Author string `json:"author,omitempty"`
Intro string `json:"intro,omitempty"`
CoverURL string `json:"cover_url,omitempty"`
Kind string `json:"kind,omitempty"`
LastChapter string `json:"last_chapter,omitempty"`
}
type BookRule ¶
type BookRule struct {
Init string `json:"init,omitempty"`
BookList string `json:"bookList,omitempty"`
Name string `json:"name,omitempty"`
Author string `json:"author,omitempty"`
BookURL string `json:"bookUrl,omitempty"`
TOCURL string `json:"tocUrl,omitempty"`
CoverURL string `json:"coverUrl,omitempty"`
Intro string `json:"intro,omitempty"`
Kind string `json:"kind,omitempty"`
LastChapter string `json:"lastChapter,omitempty"`
}
type Chapter ¶
type Client ¶
type Client struct {
HTTPClient *http.Client
MaxResponseBytes int64
MaxPages int
// contains filtered or unexported fields
}
func (*Client) CheckSource ¶
func (c *Client) CheckSource(ctx context.Context, source Source, keyword string, deep bool) (result SourceCheckResult)
CheckSource checks a source without enabling, disabling or removing it. An empty keyword performs syntax checks only; scripts are never evaluated.
func (*Client) FindAlternatives ¶
func (c *Client) FindAlternatives(ctx context.Context, sources []Source, current Book, page int) (AlternativeResult, error)
FindAlternatives searches every enabled, searchable text source. Candidate order follows the source order, then the order returned by each source.
func (*Client) IsLoggedIn ¶
func (*Client) LoadSessions ¶
func (*Client) Login ¶
Login supports the declared 大灰狼 API profile and manual website cookies. Credentials are scoped to one explicitly declared API origin, are never passed to source JavaScript and are never written to the session file.
func (*Client) LoginStatus ¶
func (*Client) SaveSessions ¶
type ContentRule ¶
type Evaluator ¶
type Evaluator struct {
// contains filtered or unexported fields
}
Evaluator implements the portable subset of Legado's source rule language. Each JavaScript invocation has its own VM; put/get variables are shared by this evaluator. Selectors return detached values or HTML nodes for chaining.
func (*Evaluator) EvalJS ¶
EvalJS exposes only portable helpers and explicitly granted JS bindings. Android/Rhino-specific APIs fail at the point of use with a named error.
func (*Evaluator) SetJSBindings ¶
SetJSBindings explicitly grants scripts trusted application capabilities. A java map augments the built-in helpers. Callers must bound any blocking native function (for example with HTTP context deadlines); VM interruption cannot preempt a Go function. Treat the supplied maps as immutable.
func (*Evaluator) SetJSContext ¶
SetJSContext binds script execution to the request lifetime. Native bindings must use this same request context for their own blocking operations.
type ImportPreview ¶
type ImportPreview struct {
Sources []Source
Added int
Updated int
Unsupported int
Collection SourceCollection
}
func BuildImportPreview ¶
func BuildImportPreview(existing, incoming []Source, location string) ImportPreview
BuildImportPreview never modifies either input. Last duplicate URL wins while keeping its first position. Imported readcli data is deliberately discarded.
type LoginField ¶
LoginField describes an input supported by this client. Script buttons that register accounts, purchase content or change server settings are not run.
func LoginFields ¶
func LoginFields(src Source) []LoginField
func LoginUIFields ¶
func LoginUIFields(src Source) []LoginField
type Source ¶
type Source struct {
Management *SourceManagement `json:"readcli,omitempty"`
LoginURL string `json:"loginUrl,omitempty"`
LoginUI json.RawMessage `json:"loginUi,omitempty"`
LoginCheckJS string `json:"loginCheckJs,omitempty"`
Extra map[string]json.RawMessage `json:"-"`
URL string `json:"bookSourceUrl"`
Name string `json:"bookSourceName"`
Group string `json:"bookSourceGroup,omitempty"`
Type int `json:"bookSourceType"`
Enabled *bool `json:"enabled,omitempty"`
Header json.RawMessage `json:"header,omitempty"`
JSLib string `json:"jsLib,omitempty"`
SearchURL string `json:"searchUrl"`
Search BookRule `json:"ruleSearch"`
BookInfo BookRule `json:"ruleBookInfo"`
TOC TOCRule `json:"ruleToc"`
Content ContentRule `json:"ruleContent"`
}
func ApplyImport ¶
func ApplyImport(existing []Source, preview ImportPreview, selected map[string]bool, enableNew bool) []Source
ApplyImport imports only explicitly selected URL keys; nil selects nothing. Existing enablement and local metadata win over downloaded settings.
func CloneSources ¶
CloneSources preserves nil slices and copies all mutable source data. It does not serialize, so unknown fields survive even when their raw JSON is invalid.
func Import ¶
Import accepts a UTF-8 JSON file or HTTP(S) URL. Malformed entries are reported with their array position. Valid unsupported sources are retained disabled so an imported collection can round-trip without losing entries.
func LoadSources ¶
func MergeSources ¶
MergeSources keeps the original API for callers without import collections. Downloaded rules replace matching URLs; local preferences remain authoritative.
func RemoveCollection ¶
RemoveCollection removes only sources whose final collection is removed. Legacy sources with no collection membership are left untouched.
func (Source) MarshalJSON ¶
func (*Source) UnmarshalJSON ¶
Some source exports serialize individual rule objects as JSON strings.
type SourceCheckResult ¶
type SourceCheckResult struct {
Status string `json:"status"`
Stage string `json:"stage"`
Detail string `json:"detail"`
CheckedAt time.Time `json:"checked_at"`
DurationMS int64 `json:"duration_ms"`
}
SourceCheckResult records one manual check without changing source settings.
type SourceCollection ¶
type SourceManagement ¶
type SourceManagement struct {
Standalone bool `json:"standalone,omitempty"`
Favorite bool `json:"favorite,omitempty"`
Tags []string `json:"tags,omitempty"`
Collections []SourceCollection `json:"collections,omitempty"`
Check *SourceCheckResult `json:"check,omitempty"`
}
SourceManagement belongs to this installation, never to a downloaded source. It is stored with the source so one atomic write includes rules and settings.