Studio Tagger (#3510)

* Studio image and parent studio support in scene tagger
* Refactor studio backend and add studio tagger
---------
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
Flashy78
2023-07-30 16:50:24 -07:00
committed by GitHub
parent d48dbeb864
commit a665a56ef0
79 changed files with 5224 additions and 1039 deletions

View File

@@ -17,6 +17,7 @@ type StashBoxGraphQLClient interface {
SearchPerformer(ctx context.Context, term string, httpRequestOptions ...client.HTTPRequestOption) (*SearchPerformer, error)
FindPerformerByID(ctx context.Context, id string, httpRequestOptions ...client.HTTPRequestOption) (*FindPerformerByID, error)
FindSceneByID(ctx context.Context, id string, httpRequestOptions ...client.HTTPRequestOption) (*FindSceneByID, error)
FindStudio(ctx context.Context, id *string, name *string, httpRequestOptions ...client.HTTPRequestOption) (*FindStudio, error)
SubmitFingerprint(ctx context.Context, input FingerprintSubmission, httpRequestOptions ...client.HTTPRequestOption) (*SubmitFingerprint, error)
Me(ctx context.Context, httpRequestOptions ...client.HTTPRequestOption) (*Me, error)
SubmitSceneDraft(ctx context.Context, input SceneDraftInput, httpRequestOptions ...client.HTTPRequestOption) (*SubmitSceneDraft, error)
@@ -125,9 +126,13 @@ type ImageFragment struct {
Height int "json:\"height\" graphql:\"height\""
}
type StudioFragment struct {
Name string "json:\"name\" graphql:\"name\""
ID string "json:\"id\" graphql:\"id\""
Urls []*URLFragment "json:\"urls\" graphql:\"urls\""
Name string "json:\"name\" graphql:\"name\""
ID string "json:\"id\" graphql:\"id\""
Urls []*URLFragment "json:\"urls\" graphql:\"urls\""
Parent *struct {
Name string "json:\"name\" graphql:\"name\""
ID string "json:\"id\" graphql:\"id\""
} "json:\"parent\" graphql:\"parent\""
Images []*ImageFragment "json:\"images\" graphql:\"images\""
}
type TagFragment struct {
@@ -215,6 +220,9 @@ type FindPerformerByID struct {
type FindSceneByID struct {
FindScene *SceneFragment "json:\"findScene\" graphql:\"findScene\""
}
type FindStudio struct {
FindStudio *StudioFragment "json:\"findStudio\" graphql:\"findStudio\""
}
type SubmitFingerprint struct {
SubmitFingerprint bool "json:\"submitFingerprint\" graphql:\"submitFingerprint\""
}
@@ -239,12 +247,77 @@ const FindSceneByFingerprintDocument = `query FindSceneByFingerprint ($fingerpri
... SceneFragment
}
}
fragment StudioFragment on Studio {
name
id
urls {
... URLFragment
}
parent {
name
id
}
images {
... ImageFragment
}
}
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment SceneFragment on Scene {
id
title
code
details
director
duration
date
urls {
... URLFragment
}
images {
... ImageFragment
}
studio {
... StudioFragment
}
tags {
... TagFragment
}
performers {
... PerformerAppearanceFragment
}
fingerprints {
... FingerprintFragment
}
}
fragment URLFragment on URL {
url
type
}
fragment ImageFragment on Image {
id
url
width
height
}
fragment TagFragment on Tag {
name
id
}
fragment PerformerAppearanceFragment on PerformerAppearance {
as
performer {
... PerformerFragment
}
}
fragment PerformerFragment on Performer {
id
name
@@ -279,76 +352,15 @@ fragment PerformerFragment on Performer {
... BodyModificationFragment
}
}
fragment SceneFragment on Scene {
id
title
code
details
director
duration
date
urls {
... URLFragment
}
images {
... ImageFragment
}
studio {
... StudioFragment
}
tags {
... TagFragment
}
performers {
... PerformerAppearanceFragment
}
fingerprints {
... FingerprintFragment
}
}
fragment URLFragment on URL {
url
type
}
fragment PerformerAppearanceFragment on PerformerAppearance {
as
performer {
... PerformerFragment
}
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
}
fragment StudioFragment on Studio {
name
id
urls {
... URLFragment
}
images {
... ImageFragment
}
}
fragment TagFragment on Tag {
name
id
}
`
func (c *Client) FindSceneByFingerprint(ctx context.Context, fingerprint FingerprintQueryInput, httpRequestOptions ...client.HTTPRequestOption) (*FindSceneByFingerprint, error) {
@@ -369,6 +381,49 @@ const FindScenesByFullFingerprintsDocument = `query FindScenesByFullFingerprints
... SceneFragment
}
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
}
fragment URLFragment on URL {
url
type
}
fragment ImageFragment on Image {
id
url
width
height
}
fragment StudioFragment on Studio {
name
id
urls {
... URLFragment
}
parent {
name
id
}
images {
... ImageFragment
}
}
fragment PerformerFragment on Performer {
id
name
@@ -403,16 +458,6 @@ fragment PerformerFragment on Performer {
... BodyModificationFragment
}
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment SceneFragment on Scene {
id
title
@@ -440,35 +485,6 @@ fragment SceneFragment on Scene {
... FingerprintFragment
}
}
fragment URLFragment on URL {
url
type
}
fragment ImageFragment on Image {
id
url
width
height
}
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
}
fragment StudioFragment on Studio {
name
id
urls {
... URLFragment
}
images {
... ImageFragment
}
}
fragment TagFragment on Tag {
name
id
@@ -499,28 +515,56 @@ const FindScenesBySceneFingerprintsDocument = `query FindScenesBySceneFingerprin
... SceneFragment
}
}
fragment StudioFragment on Studio {
fragment URLFragment on URL {
url
type
}
fragment TagFragment on Tag {
name
id
urls {
... URLFragment
}
images {
... ImageFragment
}
fragment PerformerAppearanceFragment on PerformerAppearance {
as
performer {
... PerformerFragment
}
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment URLFragment on URL {
url
type
fragment SceneFragment on Scene {
id
title
code
details
director
duration
date
urls {
... URLFragment
}
images {
... ImageFragment
}
studio {
... StudioFragment
}
tags {
... TagFragment
}
performers {
... PerformerAppearanceFragment
}
fingerprints {
... FingerprintFragment
}
}
fragment ImageFragment on Image {
id
@@ -528,10 +572,18 @@ fragment ImageFragment on Image {
width
height
}
fragment PerformerAppearanceFragment on PerformerAppearance {
as
performer {
... PerformerFragment
fragment StudioFragment on Studio {
name
id
urls {
... URLFragment
}
parent {
name
id
}
images {
... ImageFragment
}
}
fragment PerformerFragment on Performer {
@@ -568,46 +620,14 @@ fragment PerformerFragment on Performer {
... BodyModificationFragment
}
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment SceneFragment on Scene {
id
title
code
details
director
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
date
urls {
... URLFragment
}
images {
... ImageFragment
}
studio {
... StudioFragment
}
tags {
... TagFragment
}
performers {
... PerformerAppearanceFragment
}
fingerprints {
... FingerprintFragment
}
}
fragment TagFragment on Tag {
name
id
}
`
@@ -629,6 +649,29 @@ const SearchSceneDocument = `query SearchScene ($term: String!) {
... SceneFragment
}
}
fragment ImageFragment on Image {
id
url
width
height
}
fragment TagFragment on Tag {
name
id
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
}
fragment SceneFragment on Scene {
id
title
@@ -660,32 +703,16 @@ fragment URLFragment on URL {
url
type
}
fragment TagFragment on Tag {
name
id
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment ImageFragment on Image {
id
url
width
height
}
fragment StudioFragment on Studio {
name
id
urls {
... URLFragment
}
parent {
name
id
}
images {
... ImageFragment
}
@@ -730,14 +757,11 @@ fragment PerformerFragment on Performer {
... BodyModificationFragment
}
}
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
`
@@ -759,16 +783,6 @@ const SearchPerformerDocument = `query SearchPerformer ($term: String!) {
... PerformerFragment
}
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment BodyModificationFragment on BodyModification {
location
description
@@ -817,6 +831,16 @@ fragment ImageFragment on Image {
width
height
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
`
func (c *Client) SearchPerformer(ctx context.Context, term string, httpRequestOptions ...client.HTTPRequestOption) (*SearchPerformer, error) {
@@ -915,26 +939,25 @@ const FindSceneByIDDocument = `query FindSceneByID ($id: ID!) {
... SceneFragment
}
}
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
}
fragment URLFragment on URL {
fragment ImageFragment on Image {
id
url
type
width
height
}
fragment PerformerAppearanceFragment on PerformerAppearance {
as
performer {
... PerformerFragment
fragment StudioFragment on Studio {
name
id
urls {
... URLFragment
}
parent {
name
id
}
images {
... ImageFragment
}
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment TagFragment on Tag {
name
@@ -974,13 +997,11 @@ fragment PerformerFragment on Performer {
... BodyModificationFragment
}
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment BodyModificationFragment on BodyModification {
location
description
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment SceneFragment on Scene {
id
@@ -1009,22 +1030,29 @@ fragment SceneFragment on Scene {
... FingerprintFragment
}
}
fragment ImageFragment on Image {
id
fragment URLFragment on URL {
url
width
height
type
}
fragment StudioFragment on Studio {
name
id
urls {
... URLFragment
}
images {
... ImageFragment
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
}
fragment PerformerAppearanceFragment on PerformerAppearance {
as
performer {
... PerformerFragment
}
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
`
func (c *Client) FindSceneByID(ctx context.Context, id string, httpRequestOptions ...client.HTTPRequestOption) (*FindSceneByID, error) {
@@ -1040,6 +1068,51 @@ func (c *Client) FindSceneByID(ctx context.Context, id string, httpRequestOption
return &res, nil
}
const FindStudioDocument = `query FindStudio ($id: ID, $name: String) {
findStudio(id: $id, name: $name) {
... StudioFragment
}
}
fragment StudioFragment on Studio {
name
id
urls {
... URLFragment
}
parent {
name
id
}
images {
... ImageFragment
}
}
fragment URLFragment on URL {
url
type
}
fragment ImageFragment on Image {
id
url
width
height
}
`
func (c *Client) FindStudio(ctx context.Context, id *string, name *string, httpRequestOptions ...client.HTTPRequestOption) (*FindStudio, error) {
vars := map[string]interface{}{
"id": id,
"name": name,
}
var res FindStudio
if err := c.Client.Post(ctx, "FindStudio", FindStudioDocument, &res, vars, httpRequestOptions...); err != nil {
return nil, err
}
return &res, nil
}
const SubmitFingerprintDocument = `mutation SubmitFingerprint ($input: FingerprintSubmission!) {
submitFingerprint(input: $input)
}

View File

@@ -88,9 +88,9 @@ type DraftEntity struct {
ID *string `json:"id,omitempty"`
}
func (DraftEntity) IsSceneDraftPerformer() {}
func (DraftEntity) IsSceneDraftStudio() {}
func (DraftEntity) IsSceneDraftTag() {}
func (DraftEntity) IsSceneDraftStudio() {}
func (DraftEntity) IsSceneDraftPerformer() {}
type DraftEntityInput struct {
Name string `json:"name"`
@@ -116,6 +116,7 @@ type Edit struct {
// Objects to merge with the target. Only applicable to merges
MergeSources []EditTarget `json:"merge_sources,omitempty"`
Operation OperationEnum `json:"operation"`
Bot bool `json:"bot"`
Details EditDetails `json:"details,omitempty"`
// Previous state of fields being modified - null if operation is create or delete.
OldDetails EditDetails `json:"old_details,omitempty"`
@@ -154,6 +155,8 @@ type EditInput struct {
// Only required for merge type
MergeSourceIds []string `json:"merge_source_ids,omitempty"`
Comment *string `json:"comment,omitempty"`
// Edit submitted by an automated script. Requires bot permission
Bot *bool `json:"bot,omitempty"`
}
type EditQueryInput struct {
@@ -172,11 +175,15 @@ type EditQueryInput struct {
// Filter by target id
TargetID *string `json:"target_id,omitempty"`
// Filter by favorite status
IsFavorite *bool `json:"is_favorite,omitempty"`
Page int `json:"page"`
PerPage int `json:"per_page"`
Direction SortDirectionEnum `json:"direction"`
Sort EditSortEnum `json:"sort"`
IsFavorite *bool `json:"is_favorite,omitempty"`
// Filter by user voted status
Voted *UserVotedFilterEnum `json:"voted,omitempty"`
// Filter to bot edits only
IsBot *bool `json:"is_bot,omitempty"`
Page int `json:"page"`
PerPage int `json:"per_page"`
Direction SortDirectionEnum `json:"direction"`
Sort EditSortEnum `json:"sort"`
}
type EditVote struct {
@@ -542,11 +549,24 @@ type PerformerQueryInput struct {
Tattoos *BodyModificationCriterionInput `json:"tattoos,omitempty"`
Piercings *BodyModificationCriterionInput `json:"piercings,omitempty"`
// Filter by performerfavorite status for the current user
IsFavorite *bool `json:"is_favorite,omitempty"`
Page int `json:"page"`
PerPage int `json:"per_page"`
Direction SortDirectionEnum `json:"direction"`
Sort PerformerSortEnum `json:"sort"`
IsFavorite *bool `json:"is_favorite,omitempty"`
// Filter by a performer they have performed in scenes with
PerformedWith *string `json:"performed_with,omitempty"`
// Filter by a studio
StudioID *string `json:"studio_id,omitempty"`
Page int `json:"page"`
PerPage int `json:"per_page"`
Direction SortDirectionEnum `json:"direction"`
Sort PerformerSortEnum `json:"sort"`
}
type PerformerScenesInput struct {
// Filter by another performer that also performs in the scenes
PerformedWith *string `json:"performed_with,omitempty"`
// Filter by a studio
StudioID *string `json:"studio_id,omitempty"`
// Filter by tags
Tags *MultiIDCriterionInput `json:"tags,omitempty"`
}
type PerformerStudio struct {
@@ -689,7 +709,9 @@ type SceneDestroyInput struct {
type SceneDraft struct {
ID *string `json:"id,omitempty"`
Title *string `json:"title,omitempty"`
Code *string `json:"code,omitempty"`
Details *string `json:"details,omitempty"`
Director *string `json:"director,omitempty"`
URL *URL `json:"url,omitempty"`
Date *string `json:"date,omitempty"`
Studio SceneDraftStudio `json:"studio,omitempty"`
@@ -774,11 +796,13 @@ type SceneQueryInput struct {
// Filter to only include scenes with these fingerprints
Fingerprints *MultiStringCriterionInput `json:"fingerprints,omitempty"`
// Filter by favorited entity
Favorites *FavoriteFilter `json:"favorites,omitempty"`
Page int `json:"page"`
PerPage int `json:"per_page"`
Direction SortDirectionEnum `json:"direction"`
Sort SceneSortEnum `json:"sort"`
Favorites *FavoriteFilter `json:"favorites,omitempty"`
// Filter to scenes with fingerprints submitted by the user
HasFingerprintSubmissions *bool `json:"has_fingerprint_submissions,omitempty"`
Page int `json:"page"`
PerPage int `json:"per_page"`
Direction SortDirectionEnum `json:"direction"`
Sort SceneSortEnum `json:"sort"`
}
type SceneUpdateInput struct {
@@ -847,16 +871,17 @@ type StringCriterionInput struct {
}
type Studio struct {
ID string `json:"id"`
Name string `json:"name"`
Urls []*URL `json:"urls,omitempty"`
Parent *Studio `json:"parent,omitempty"`
ChildStudios []*Studio `json:"child_studios,omitempty"`
Images []*Image `json:"images,omitempty"`
Deleted bool `json:"deleted"`
IsFavorite bool `json:"is_favorite"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
ID string `json:"id"`
Name string `json:"name"`
Urls []*URL `json:"urls,omitempty"`
Parent *Studio `json:"parent,omitempty"`
ChildStudios []*Studio `json:"child_studios,omitempty"`
Images []*Image `json:"images,omitempty"`
Deleted bool `json:"deleted"`
IsFavorite bool `json:"is_favorite"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
Performers *QueryPerformersResultType `json:"performers,omitempty"`
}
func (Studio) IsSceneDraftStudio() {}
@@ -1775,6 +1800,7 @@ const (
PerformerSortEnumOCounter PerformerSortEnum = "O_COUNTER"
PerformerSortEnumCareerStartYear PerformerSortEnum = "CAREER_START_YEAR"
PerformerSortEnumDebut PerformerSortEnum = "DEBUT"
PerformerSortEnumLastScene PerformerSortEnum = "LAST_SCENE"
PerformerSortEnumCreatedAt PerformerSortEnum = "CREATED_AT"
PerformerSortEnumUpdatedAt PerformerSortEnum = "UPDATED_AT"
)
@@ -1786,6 +1812,7 @@ var AllPerformerSortEnum = []PerformerSortEnum{
PerformerSortEnumOCounter,
PerformerSortEnumCareerStartYear,
PerformerSortEnumDebut,
PerformerSortEnumLastScene,
PerformerSortEnumCreatedAt,
PerformerSortEnumUpdatedAt,
}
@@ -2136,6 +2163,51 @@ func (e TargetTypeEnum) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(e.String()))
}
type UserVotedFilterEnum string
const (
UserVotedFilterEnumAbstain UserVotedFilterEnum = "ABSTAIN"
UserVotedFilterEnumAccept UserVotedFilterEnum = "ACCEPT"
UserVotedFilterEnumReject UserVotedFilterEnum = "REJECT"
UserVotedFilterEnumNotVoted UserVotedFilterEnum = "NOT_VOTED"
)
var AllUserVotedFilterEnum = []UserVotedFilterEnum{
UserVotedFilterEnumAbstain,
UserVotedFilterEnumAccept,
UserVotedFilterEnumReject,
UserVotedFilterEnumNotVoted,
}
func (e UserVotedFilterEnum) IsValid() bool {
switch e {
case UserVotedFilterEnumAbstain, UserVotedFilterEnumAccept, UserVotedFilterEnumReject, UserVotedFilterEnumNotVoted:
return true
}
return false
}
func (e UserVotedFilterEnum) String() string {
return string(e)
}
func (e *UserVotedFilterEnum) UnmarshalGQL(v interface{}) error {
str, ok := v.(string)
if !ok {
return fmt.Errorf("enums must be strings")
}
*e = UserVotedFilterEnum(str)
if !e.IsValid() {
return fmt.Errorf("%s is not a valid UserVotedFilterEnum", str)
}
return nil
}
func (e UserVotedFilterEnum) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(e.String()))
}
type ValidSiteTypeEnum string
const (