Documentation
¶
Index ¶
- func LoadJSONDir(dir string) ([]models.Scene, error)
- func LoadJSONFiles(paths []string) ([]models.Scene, error)
- func MergeStrings(existing, incoming []string) []string
- func Normalize(s string) string
- func NormalizeName(s string) string
- func ResolutionTags(width int) []string
- type FieldSource
- type MatchConfidence
- type MatchResult
- type MergedScene
- type SceneIndex
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func LoadJSONDir ¶
LoadJSONDir reads all *.json files in a directory.
func LoadJSONFiles ¶
LoadJSONFiles reads FSS JSON files and returns all scenes. Files that don't match the expected format are silently skipped.
func MergeStrings ¶
MergeStrings returns the ordered union of two slices, preserving the order from existing first, then appending any incoming entries not already present.
func Normalize ¶
Normalize lowercases, folds accents, splits camelCase, and collapses runs of non-letter/non-digit characters into single spaces. Unlike a plain [a-z0-9] strip it preserves letters and digits of every script, so Cyrillic and CJK titles survive instead of normalizing to an empty string.
func NormalizeName ¶
NormalizeName is the canonical key for a performer, tag, category or studio name: surrounding whitespace removed, internal runs collapsed, case folded. Two spellings that differ only in case or spacing map to one key.
It is exported so that anything filtering on these names agrees with how merging deduplicates them — otherwise `--from-studio "ABC"` would miss a stored `"ABC "` that MergeScenes considers the same studio.
This is deliberately not Normalize, which strips scene *titles* for filename matching and is far more aggressive.
func ResolutionTags ¶
ResolutionTags returns the single highest resolution tag for the video width.
Types ¶
type FieldSource ¶
type FieldSource struct {
// Site is the site ID whose value was kept. Empty when the value came
// from outside the scene set — the existing Stash date, for instance.
Site string
// Discarded holds the competing values that lost, as "siteID: value",
// in the order the scenes were merged.
Discarded []string
}
FieldSource is the provenance of one merged scalar field.
Merging picks a winner per field — first non-empty title, longest description, earliest date — and the losers are otherwise unrecoverable. Recording them is what distinguishes a merge from a guess: a caller can show that two sites disagreed on a scene's date instead of silently presenting one.
func (FieldSource) Conflicted ¶
func (f FieldSource) Conflicted() bool
Conflicted reports whether more than one distinct value was offered.
type MatchConfidence ¶
type MatchConfidence int
MatchConfidence indicates how strong a filename-to-title match is.
const ( MatchExact MatchConfidence = iota MatchSubstring MatchNone MatchAmbiguous )
Confidence levels, ordered from strongest to weakest. MatchNone means no candidate matched; MatchAmbiguous means several distinct titles did and the caller must disambiguate.
func (MatchConfidence) String ¶
func (c MatchConfidence) String() string
type MatchResult ¶
type MatchResult struct {
Confidence MatchConfidence
Scenes []models.Scene // all matching FSS scenes (possibly from multiple sites)
Candidates int // for ambiguous: how many distinct titles matched
}
MatchResult holds the matched scenes and confidence level for a single filename lookup.
type MergedScene ¶
type MergedScene struct {
Title string
Description string
Date time.Time
URLs []string
Tags []string
Categories []string
Performers []string
Studio string
Thumbnail string
Duration int
Width int
Height int
Resolution string
Sites []string // which site IDs contributed
// Sources records, per scalar field, which site's value was kept and which
// competing values were dropped. Keys are the lowercase field names listed
// in scalarFields. Absent for fields no site supplied.
Sources map[string]FieldSource
}
MergedScene holds the combined metadata from one or more FSS scenes, ready to be applied to a Stash scene.
func MergeScenes ¶
func MergeScenes(scenes []models.Scene, existingDate time.Time) MergedScene
MergeScenes combines metadata from multiple FSS scenes (potentially from different sites) into a single MergedScene. Optionally incorporates the existing Stash scene date for earliest-date logic.
Performer, tag, category and studio names are trimmed before deduplication, and entries that trim to nothing are dropped.
This is not cosmetic tidying. Several site APIs return names with stray whitespace — Aylo serves "Nikki Nuttz " with a trailing space — and every downstream consumer compares these strings exactly:
- deduplication here is by exact string, so "Nikki Nuttz " from one site and "Nikki Nuttz" from another survived as two separate performers, which defeats the point of merging across sites;
- `fss stash import` looks performers, tags and studios up in Stash **by name**, so the untrimmed variant never matches the existing entity and `--apply` creates a duplicate with a trailing space.
Trimming here rather than only in the scrapers also repairs catalogues that were already written to disk with the stray whitespace, which no scraper-side fix can do without a full re-scrape. Scrapers should still avoid emitting it.
Deduplication is by canonical key (see normName): case-folded, with runs of whitespace collapsed. The *stored* value keeps its original case — sites legitimately differ on capitalisation and folding it would change which name is written to Stash — but "Big Tits" and "big tits" from two sites are one entry, not two.
type SceneIndex ¶
type SceneIndex struct {
// contains filtered or unexported fields
}
SceneIndex is a precomputed index of scene titles for fast filename matching.
func BuildIndex ¶
func BuildIndex(scenes []models.Scene) *SceneIndex
BuildIndex creates a SceneIndex from a slice of scenes, building exact and substring lookup tables.
func (*SceneIndex) Match ¶
func (idx *SceneIndex) Match(filename string, fileDurationSec float64) MatchResult
Match finds FSS scenes matching a filename. fileDurationSec is the duration of the Stash file in seconds (0 means unknown / skip check).