match

package
v1.30.1 Latest Latest
Warning

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

Go to latest
Published: Aug 25, 2026 License: GPL-3.0 Imports: 14 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func LoadJSONDir

func LoadJSONDir(dir string) ([]models.Scene, error)

LoadJSONDir reads all *.json files in a directory.

func LoadJSONFiles

func LoadJSONFiles(paths []string) ([]models.Scene, error)

LoadJSONFiles reads FSS JSON files and returns all scenes. Files that don't match the expected format are silently skipped.

func MergeStrings

func MergeStrings(existing, incoming []string) []string

MergeStrings returns the ordered union of two slices, preserving the order from existing first, then appending any incoming entries not already present.

func Normalize

func Normalize(s string) string

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

func NormalizeName(s string) string

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

func ResolutionTags(width int) []string

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).

Jump to

Keyboard shortcuts

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