Documentation
¶
Overview ¶
Package stash is the plugin's GraphQL client for its parent Stash instance. Modeled on StashJanitor/internal/stash (same author, GPL): raw queries over net/http, typed errors, no generated client.
Auth is either the session cookie Stash hands the plugin process or an API key from plugin settings. The API key wins when both are present: session cookies expire mid-run on long tasks (stashapp/stash#5332), so PLAN.md mandates preferring the key.
Index ¶
- type Caption
- type Client
- func (c *Client) Execute(ctx context.Context, query string, variables map[string]any, out any) error
- func (c *Client) FindScene(ctx context.Context, id string) (*Scene, error)
- func (c *Client) FindScenesPage(ctx context.Context, page, perPage int) ([]Scene, int, error)
- func (c *Client) MetadataScan(ctx context.Context, paths []string) (string, error)
- func (c *Client) PluginSettings(ctx context.Context, pluginID string) (map[string]any, error)
- func (c *Client) ProbeCaptions(ctx context.Context) bool
- func (c *Client) UseAPIKey(key string)
- type GraphQLError
- type Performer
- type Scene
- type SceneFile
- type StashID
- type Studio
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Caption ¶
type Caption struct {
LanguageCode string `json:"language_code"`
CaptionType string `json:"caption_type"`
}
Caption is one attached caption as Stash reports it.
type Client ¶
type Client struct {
// Endpoint is the base URL as given to NewClient, kept for logging.
Endpoint string
// SupportsCaptions is set by ProbeCaptions. Zero value means "not yet
// probed"; callers must probe before building scene queries that touch
// captions, because an unknown GraphQL field fails the entire query.
SupportsCaptions bool
// contains filtered or unexported fields
}
Client is a Stash GraphQL client. Safe for concurrent use.
func NewClient ¶
NewClient builds a Client for the given base URL (scheme://host:port).
apiKey wins over cookie when both are present — that precedence lives in the shared client now, for the same reason it lived here: a session cookie expires mid-run and fails a long task partway through.
func (*Client) Execute ¶
func (c *Client) Execute(ctx context.Context, query string, variables map[string]any, out any) error
Execute posts one GraphQL query and decodes the `data` field into out (a non-nil pointer, or nil when the caller ignores the result).
func (*Client) FindScene ¶
FindScene fetches one scene by id. Caption fields are only requested when ProbeCaptions established they exist.
func (*Client) FindScenesPage ¶
FindScenesPage returns one page of all scenes, id-ascending, plus the total count — the iteration backbone for library-wide tasks.
func (*Client) MetadataScan ¶
MetadataScan triggers a scan of the given paths — the only way to attach a genuinely new caption, since captions are read-only in GraphQL (PLAN.md delivery constraint 3). Returns the job id.
func (*Client) PluginSettings ¶
PluginSettings fetches this plugin's settings map from Stash's configuration. Returns an empty map when the plugin has no settings yet.
func (*Client) ProbeCaptions ¶
ProbeCaptions asks, once and cheaply, whether this Stash exposes Scene.captions — the schema shifts between releases and an unknown field fails an entire query, so this must never be discovered mid-task (pattern from stash-subs stash.py:Client.probe_captions).
func (*Client) UseAPIKey ¶
UseAPIKey switches authentication to an API key.
The plugin cannot know the key up front: it connects with the session cookie Stash supplies, reads its own settings over that connection, and only then learns whether an operator configured one. Preferring the key from that point on is deliberate — session cookies expire mid-run, and a long task then fails partway through (stashapp/stash#5332).
The shared client is immutable, so this rebuilds it rather than mutating auth underneath in-flight requests.
type GraphQLError ¶
GraphQLError is a non-empty `errors` array in the GraphQL response — schema mismatches (unknown field) and auth failures surface here.
An alias for the shared type, so a value returned by the upstream client satisfies it exactly. Each entry now also keeps its `path` and `extensions`.
type Performer ¶
type Performer struct {
Name string `json:"name"`
}
Performer is one of a scene's performers (name only, same reasoning).
type Scene ¶
type Scene struct {
ID string `json:"id"`
Title string `json:"title"`
// Date is Stash's YYYY-MM-DD release date, empty when unset.
Date string `json:"date"`
Studio *Studio `json:"studio"`
Performers []Performer `json:"performers"`
Files []SceneFile `json:"files"`
Captions []Caption `json:"captions"`
StashIDs []StashID `json:"stash_ids"`
}
Scene is the subset of Scene the plugin needs.
func (Scene) PerformerNames ¶
PerformerNames returns the scene's performer names, or nil when it has none — nil rather than an empty slice so callers get the same "absent" shape msclient.UploadRequest's omitempty expects.
func (Scene) StudioName ¶
StudioName returns the scene's studio name, or "" when it has none.
type SceneFile ¶
type SceneFile struct {
Path string `json:"path"`
Duration float64 `json:"duration"`
Fingerprints []struct {
Type string `json:"type"`
Value string `json:"value"`
} `json:"fingerprints"`
}
SceneFile is one file backing a scene, with the fingerprints moansubs keys on. Duration is seconds (Stash's unit for VideoFile.duration).
func (SceneFile) Fingerprint ¶
Fingerprint returns the value of the named fingerprint type ("oshash", "phash", "md5"), or "" when absent.
type StashID ¶
StashID is one of a scene's stash-box identities (WP-C9a): Endpoint is the stash-box GraphQL URL exactly as Stash reports it (normalized by internal/hash before it goes anywhere near the moansubs server), StashID its scene id on that stash-box. `stash_ids { endpoint stash_id }` has existed on Scene since Stash 0.10 — unlike captions, this needs no probe: it's safe to request unconditionally.