diff --git a/graphql/stash-box/query.graphql b/graphql/stash-box/query.graphql index 25c08c61b0..039be28afe 100644 --- a/graphql/stash-box/query.graphql +++ b/graphql/stash-box/query.graphql @@ -20,6 +20,13 @@ fragment StudioFragment on Studio { parent { name id + aliases + urls { + ...URLFragment + } + images { + ...ImageFragment + } } images { ...ImageFragment diff --git a/pkg/stashbox/graphql/generated_client.go b/pkg/stashbox/graphql/generated_client.go index e9761c1c1b..801b38b4d0 100644 --- a/pkg/stashbox/graphql/generated_client.go +++ b/pkg/stashbox/graphql/generated_client.go @@ -527,22 +527,43 @@ func (t *SceneFragment) GetFingerprints() []*FingerprintFragment { } type StudioFragment_Parent struct { - ID string "json:\"id\" graphql:\"id\"" - Name string "json:\"name\" graphql:\"name\"" + Aliases []string "json:\"aliases\" graphql:\"aliases\"" + ID string "json:\"id\" graphql:\"id\"" + Images []*ImageFragment "json:\"images\" graphql:\"images\"" + Name string "json:\"name\" graphql:\"name\"" + Urls []*URLFragment "json:\"urls\" graphql:\"urls\"" } +func (t *StudioFragment_Parent) GetAliases() []string { + if t == nil { + t = &StudioFragment_Parent{} + } + return t.Aliases +} func (t *StudioFragment_Parent) GetID() string { if t == nil { t = &StudioFragment_Parent{} } return t.ID } +func (t *StudioFragment_Parent) GetImages() []*ImageFragment { + if t == nil { + t = &StudioFragment_Parent{} + } + return t.Images +} func (t *StudioFragment_Parent) GetName() string { if t == nil { t = &StudioFragment_Parent{} } return t.Name } +func (t *StudioFragment_Parent) GetUrls() []*URLFragment { + if t == nil { + t = &StudioFragment_Parent{} + } + return t.Urls +} type TagFragment_Category struct { Description *string "json:\"description,omitempty\" graphql:\"description\"" @@ -570,22 +591,43 @@ func (t *TagFragment_Category) GetName() string { } type SceneFragment_Studio_StudioFragment_Parent struct { - ID string "json:\"id\" graphql:\"id\"" - Name string "json:\"name\" graphql:\"name\"" + Aliases []string "json:\"aliases\" graphql:\"aliases\"" + ID string "json:\"id\" graphql:\"id\"" + Images []*ImageFragment "json:\"images\" graphql:\"images\"" + Name string "json:\"name\" graphql:\"name\"" + Urls []*URLFragment "json:\"urls\" graphql:\"urls\"" } +func (t *SceneFragment_Studio_StudioFragment_Parent) GetAliases() []string { + if t == nil { + t = &SceneFragment_Studio_StudioFragment_Parent{} + } + return t.Aliases +} func (t *SceneFragment_Studio_StudioFragment_Parent) GetID() string { if t == nil { t = &SceneFragment_Studio_StudioFragment_Parent{} } return t.ID } +func (t *SceneFragment_Studio_StudioFragment_Parent) GetImages() []*ImageFragment { + if t == nil { + t = &SceneFragment_Studio_StudioFragment_Parent{} + } + return t.Images +} func (t *SceneFragment_Studio_StudioFragment_Parent) GetName() string { if t == nil { t = &SceneFragment_Studio_StudioFragment_Parent{} } return t.Name } +func (t *SceneFragment_Studio_StudioFragment_Parent) GetUrls() []*URLFragment { + if t == nil { + t = &SceneFragment_Studio_StudioFragment_Parent{} + } + return t.Urls +} type SceneFragment_Tags_TagFragment_Category struct { Description *string "json:\"description,omitempty\" graphql:\"description\"" @@ -613,22 +655,43 @@ func (t *SceneFragment_Tags_TagFragment_Category) GetName() string { } type FindScenesBySceneFingerprints_FindScenesBySceneFingerprints_SceneFragment_Studio_StudioFragment_Parent struct { - ID string "json:\"id\" graphql:\"id\"" - Name string "json:\"name\" graphql:\"name\"" + Aliases []string "json:\"aliases\" graphql:\"aliases\"" + ID string "json:\"id\" graphql:\"id\"" + Images []*ImageFragment "json:\"images\" graphql:\"images\"" + Name string "json:\"name\" graphql:\"name\"" + Urls []*URLFragment "json:\"urls\" graphql:\"urls\"" } +func (t *FindScenesBySceneFingerprints_FindScenesBySceneFingerprints_SceneFragment_Studio_StudioFragment_Parent) GetAliases() []string { + if t == nil { + t = &FindScenesBySceneFingerprints_FindScenesBySceneFingerprints_SceneFragment_Studio_StudioFragment_Parent{} + } + return t.Aliases +} func (t *FindScenesBySceneFingerprints_FindScenesBySceneFingerprints_SceneFragment_Studio_StudioFragment_Parent) GetID() string { if t == nil { t = &FindScenesBySceneFingerprints_FindScenesBySceneFingerprints_SceneFragment_Studio_StudioFragment_Parent{} } return t.ID } +func (t *FindScenesBySceneFingerprints_FindScenesBySceneFingerprints_SceneFragment_Studio_StudioFragment_Parent) GetImages() []*ImageFragment { + if t == nil { + t = &FindScenesBySceneFingerprints_FindScenesBySceneFingerprints_SceneFragment_Studio_StudioFragment_Parent{} + } + return t.Images +} func (t *FindScenesBySceneFingerprints_FindScenesBySceneFingerprints_SceneFragment_Studio_StudioFragment_Parent) GetName() string { if t == nil { t = &FindScenesBySceneFingerprints_FindScenesBySceneFingerprints_SceneFragment_Studio_StudioFragment_Parent{} } return t.Name } +func (t *FindScenesBySceneFingerprints_FindScenesBySceneFingerprints_SceneFragment_Studio_StudioFragment_Parent) GetUrls() []*URLFragment { + if t == nil { + t = &FindScenesBySceneFingerprints_FindScenesBySceneFingerprints_SceneFragment_Studio_StudioFragment_Parent{} + } + return t.Urls +} type FindScenesBySceneFingerprints_FindScenesBySceneFingerprints_SceneFragment_Tags_TagFragment_Category struct { Description *string "json:\"description,omitempty\" graphql:\"description\"" @@ -656,22 +719,43 @@ func (t *FindScenesBySceneFingerprints_FindScenesBySceneFingerprints_SceneFragme } type SearchScene_SearchScene_SceneFragment_Studio_StudioFragment_Parent struct { - ID string "json:\"id\" graphql:\"id\"" - Name string "json:\"name\" graphql:\"name\"" + Aliases []string "json:\"aliases\" graphql:\"aliases\"" + ID string "json:\"id\" graphql:\"id\"" + Images []*ImageFragment "json:\"images\" graphql:\"images\"" + Name string "json:\"name\" graphql:\"name\"" + Urls []*URLFragment "json:\"urls\" graphql:\"urls\"" } +func (t *SearchScene_SearchScene_SceneFragment_Studio_StudioFragment_Parent) GetAliases() []string { + if t == nil { + t = &SearchScene_SearchScene_SceneFragment_Studio_StudioFragment_Parent{} + } + return t.Aliases +} func (t *SearchScene_SearchScene_SceneFragment_Studio_StudioFragment_Parent) GetID() string { if t == nil { t = &SearchScene_SearchScene_SceneFragment_Studio_StudioFragment_Parent{} } return t.ID } +func (t *SearchScene_SearchScene_SceneFragment_Studio_StudioFragment_Parent) GetImages() []*ImageFragment { + if t == nil { + t = &SearchScene_SearchScene_SceneFragment_Studio_StudioFragment_Parent{} + } + return t.Images +} func (t *SearchScene_SearchScene_SceneFragment_Studio_StudioFragment_Parent) GetName() string { if t == nil { t = &SearchScene_SearchScene_SceneFragment_Studio_StudioFragment_Parent{} } return t.Name } +func (t *SearchScene_SearchScene_SceneFragment_Studio_StudioFragment_Parent) GetUrls() []*URLFragment { + if t == nil { + t = &SearchScene_SearchScene_SceneFragment_Studio_StudioFragment_Parent{} + } + return t.Urls +} type SearchScene_SearchScene_SceneFragment_Tags_TagFragment_Category struct { Description *string "json:\"description,omitempty\" graphql:\"description\"" @@ -699,22 +783,43 @@ func (t *SearchScene_SearchScene_SceneFragment_Tags_TagFragment_Category) GetNam } type FindSceneByID_FindScene_SceneFragment_Studio_StudioFragment_Parent struct { - ID string "json:\"id\" graphql:\"id\"" - Name string "json:\"name\" graphql:\"name\"" + Aliases []string "json:\"aliases\" graphql:\"aliases\"" + ID string "json:\"id\" graphql:\"id\"" + Images []*ImageFragment "json:\"images\" graphql:\"images\"" + Name string "json:\"name\" graphql:\"name\"" + Urls []*URLFragment "json:\"urls\" graphql:\"urls\"" } +func (t *FindSceneByID_FindScene_SceneFragment_Studio_StudioFragment_Parent) GetAliases() []string { + if t == nil { + t = &FindSceneByID_FindScene_SceneFragment_Studio_StudioFragment_Parent{} + } + return t.Aliases +} func (t *FindSceneByID_FindScene_SceneFragment_Studio_StudioFragment_Parent) GetID() string { if t == nil { t = &FindSceneByID_FindScene_SceneFragment_Studio_StudioFragment_Parent{} } return t.ID } +func (t *FindSceneByID_FindScene_SceneFragment_Studio_StudioFragment_Parent) GetImages() []*ImageFragment { + if t == nil { + t = &FindSceneByID_FindScene_SceneFragment_Studio_StudioFragment_Parent{} + } + return t.Images +} func (t *FindSceneByID_FindScene_SceneFragment_Studio_StudioFragment_Parent) GetName() string { if t == nil { t = &FindSceneByID_FindScene_SceneFragment_Studio_StudioFragment_Parent{} } return t.Name } +func (t *FindSceneByID_FindScene_SceneFragment_Studio_StudioFragment_Parent) GetUrls() []*URLFragment { + if t == nil { + t = &FindSceneByID_FindScene_SceneFragment_Studio_StudioFragment_Parent{} + } + return t.Urls +} type FindSceneByID_FindScene_SceneFragment_Tags_TagFragment_Category struct { Description *string "json:\"description,omitempty\" graphql:\"description\"" @@ -742,22 +847,43 @@ func (t *FindSceneByID_FindScene_SceneFragment_Tags_TagFragment_Category) GetNam } type FindStudio_FindStudio_StudioFragment_Parent struct { - ID string "json:\"id\" graphql:\"id\"" - Name string "json:\"name\" graphql:\"name\"" + Aliases []string "json:\"aliases\" graphql:\"aliases\"" + ID string "json:\"id\" graphql:\"id\"" + Images []*ImageFragment "json:\"images\" graphql:\"images\"" + Name string "json:\"name\" graphql:\"name\"" + Urls []*URLFragment "json:\"urls\" graphql:\"urls\"" } +func (t *FindStudio_FindStudio_StudioFragment_Parent) GetAliases() []string { + if t == nil { + t = &FindStudio_FindStudio_StudioFragment_Parent{} + } + return t.Aliases +} func (t *FindStudio_FindStudio_StudioFragment_Parent) GetID() string { if t == nil { t = &FindStudio_FindStudio_StudioFragment_Parent{} } return t.ID } +func (t *FindStudio_FindStudio_StudioFragment_Parent) GetImages() []*ImageFragment { + if t == nil { + t = &FindStudio_FindStudio_StudioFragment_Parent{} + } + return t.Images +} func (t *FindStudio_FindStudio_StudioFragment_Parent) GetName() string { if t == nil { t = &FindStudio_FindStudio_StudioFragment_Parent{} } return t.Name } +func (t *FindStudio_FindStudio_StudioFragment_Parent) GetUrls() []*URLFragment { + if t == nil { + t = &FindStudio_FindStudio_StudioFragment_Parent{} + } + return t.Urls +} type FindTag_FindTag_TagFragment_Category struct { Description *string "json:\"description,omitempty\" graphql:\"description\"" @@ -1044,6 +1170,13 @@ fragment StudioFragment on Studio { parent { name id + aliases + urls { + ... URLFragment + } + images { + ... ImageFragment + } } images { ... ImageFragment @@ -1188,6 +1321,13 @@ fragment StudioFragment on Studio { parent { name id + aliases + urls { + ... URLFragment + } + images { + ... ImageFragment + } } images { ... ImageFragment @@ -1490,6 +1630,13 @@ fragment StudioFragment on Studio { parent { name id + aliases + urls { + ... URLFragment + } + images { + ... ImageFragment + } } images { ... ImageFragment @@ -1597,6 +1744,13 @@ fragment StudioFragment on Studio { parent { name id + aliases + urls { + ... URLFragment + } + images { + ... ImageFragment + } } images { ... ImageFragment diff --git a/pkg/stashbox/graphql/generated_models.go b/pkg/stashbox/graphql/generated_models.go index e52c61fb27..9e1646ffb6 100644 --- a/pkg/stashbox/graphql/generated_models.go +++ b/pkg/stashbox/graphql/generated_models.go @@ -46,7 +46,25 @@ type ActivateNewUserInput struct { Password string `json:"password"` } -type ApplyEditInput struct { +type AmendEditInput struct { + ID string `json:"id"` + Reason string `json:"reason"` + // Fields to remove from the diff (e.g., ["name", "disambiguation"]) + RemoveFields []string `json:"remove_fields,omitempty"` + // Array items to remove from added arrays + RemoveAddedItems []*AmendItemRemoval `json:"remove_added_items,omitempty"` + // Array items to remove from removed arrays + RemoveRemovedItems []*AmendItemRemoval `json:"remove_removed_items,omitempty"` +} + +type AmendItemRemoval struct { + // Field name (e.g., "aliases", "urls", "images") + Field string `json:"field"` + // Indices to remove from the array + Indices []int `json:"indices"` +} + +type ApproveEditInput struct { ID string `json:"id"` } @@ -75,6 +93,25 @@ type CancelEditInput struct { ID string `json:"id"` } +type ClusterMember struct { + Hash string `json:"hash"` + SceneSubmissions []*ClusterSceneSubmission `json:"scene_submissions"` +} + +type ClusterOshash struct { + Hash string `json:"hash"` + Submissions int `json:"submissions"` + Reports int `json:"reports"` +} + +type ClusterSceneSubmission struct { + Scene *Scene `json:"scene"` + Submissions int `json:"submissions"` + Reports int `json:"reports"` + Durations []*DurationCount `json:"durations"` + LinkedFingerprints []*ClusterOshash `json:"linked_fingerprints"` +} + type CommentCommentedEdit struct { Comment *EditComment `json:"comment"` } @@ -98,6 +135,16 @@ type DateCriterionInput struct { Modifier CriterionModifier `json:"modifier"` } +type DeleteEditInput struct { + ID string `json:"id"` + Reason string `json:"reason"` +} + +type DeleteFingerprintSubmissionsInput struct { + Fingerprints []*FingerprintQueryInput `json:"fingerprints"` + SceneID string `json:"scene_id"` +} + type DownvoteOwnEdit struct { Edit *Edit `json:"edit"` } @@ -137,6 +184,11 @@ type DraftSubmissionStatus struct { ID *string `json:"id,omitempty"` } +type DurationCount struct { + Duration int `json:"duration"` + Count int `json:"count"` +} + type Edit struct { ID string `json:"id"` User *User `json:"user,omitempty"` @@ -173,7 +225,11 @@ type EditComment struct { User *User `json:"user,omitempty"` Date time.Time `json:"date"` Comment string `json:"comment"` - Edit *Edit `json:"edit"` + // Set when a moderator has edited the comment text + Updated *time.Time `json:"updated,omitempty"` + // Whether the comment is hidden from public view. Hidden comments are only returned to moderators. + Hidden bool `json:"hidden"` + Edit *Edit `json:"edit"` } type EditCommentInput struct { @@ -283,6 +339,30 @@ type Fingerprint struct { UserReported bool `json:"user_reported"` } +type FingerprintBatchSubmission struct { + SceneID string `json:"scene_id"` + Hash string `json:"hash"` + Algorithm FingerprintAlgorithm `json:"algorithm"` + Duration int `json:"duration"` +} + +type FingerprintCluster struct { + Members []*ClusterMember `json:"members"` +} + +type FingerprintClustersInput struct { + SceneID string `json:"scene_id"` + Distance int `json:"distance"` +} + +type FingerprintClustersResult struct { + Clusters []*FingerprintCluster `json:"clusters"` + // True when BFS expansion was capped by any of its limits (scene count, + // member count, or iteration count); some related fingerprints may be + // missing from the response. + Truncated bool `json:"truncated"` +} + type FingerprintEditInput struct { UserIds []string `json:"user_ids,omitempty"` Hash string `json:"hash"` @@ -301,6 +381,14 @@ type FingerprintInput struct { Duration int `json:"duration"` } +type FingerprintMovedScene struct { + SourceScene *Scene `json:"source_scene"` + TargetScene *Scene `json:"target_scene"` + FingerprintHash string `json:"fingerprint_hash"` +} + +func (FingerprintMovedScene) IsNotificationData() {} + type FingerprintQueryInput struct { Hash string `json:"hash"` Algorithm FingerprintAlgorithm `json:"algorithm"` @@ -313,6 +401,15 @@ type FingerprintSubmission struct { Vote *FingerprintSubmissionType `json:"vote,omitempty"` } +type FingerprintSubmissionResult struct { + // The fingerprint hash that was submitted + Hash string `json:"hash"` + // The scene ID that was submitted to + SceneID string `json:"scene_id"` + // Error message if submission failed + Error *string `json:"error,omitempty"` +} + type FingerprintedSceneEdit struct { Edit *Edit `json:"edit"` } @@ -324,6 +421,11 @@ type FuzzyDate struct { Accuracy DateAccuracyEnum `json:"accuracy"` } +type GenderFacet struct { + Gender GenderEnum `json:"gender"` + Count int `json:"count"` +} + type GenerateInviteCodeInput struct { Keys *int `json:"keys,omitempty"` Uses *int `json:"uses,omitempty"` @@ -340,6 +442,14 @@ type HairColorCriterionInput struct { Modifier CriterionModifier `json:"modifier"` } +type HideEditCommentInput struct { + // ID of the comment to hide/unhide + ID string `json:"id"` + Hidden bool `json:"hidden"` + // Reason for the change, recorded in the moderation audit log + Reason *string `json:"reason,omitempty"` +} + type IDCriterionInput struct { Value []string `json:"value"` Modifier CriterionModifier `json:"modifier"` @@ -389,6 +499,30 @@ type Measurements struct { Hip *int `json:"hip,omitempty"` } +type ModAudit struct { + ID string `json:"id"` + Action ModAuditActionEnum `json:"action"` + User *User `json:"user,omitempty"` + TargetID string `json:"target_id"` + TargetType string `json:"target_type"` + Data string `json:"data"` + Reason *string `json:"reason,omitempty"` + CreatedAt time.Time `json:"created_at"` +} + +type ModAuditQueryInput struct { + Page int `json:"page"` + PerPage int `json:"per_page"` + Action *ModAuditActionEnum `json:"action,omitempty"` + UserID *string `json:"user_id,omitempty"` +} + +type MoveFingerprintSubmissionsInput struct { + Fingerprints []*FingerprintQueryInput `json:"fingerprints"` + SourceSceneID string `json:"source_scene_id"` + TargetSceneID string `json:"target_scene_id"` +} + type MultiIDCriterionInput struct { Value []string `json:"value,omitempty"` Modifier CriterionModifier `json:"modifier"` @@ -408,9 +542,10 @@ type NewUserInput struct { } type Notification struct { - Created time.Time `json:"created"` - Read bool `json:"read"` - Data NotificationData `json:"data"` + Created time.Time `json:"created"` + Read bool `json:"read"` + Level NotificationLevel `json:"level"` + Data NotificationData `json:"data"` } type Performer struct { @@ -686,6 +821,15 @@ type PerformerScenesInput struct { Tags *MultiIDCriterionInput `json:"tags,omitempty"` } +type PerformerSearchFacets struct { + Genders []*GenderFacet `json:"genders"` +} + +type PerformerSearchFilter struct { + // Filter by gender + Gender *GenderEnum `json:"gender,omitempty"` +} + type PerformerStudio struct { Studio *Studio `json:"studio"` SceneCount int `json:"scene_count"` @@ -748,6 +892,11 @@ type QueryExistingSceneResult struct { Scenes []*Scene `json:"scenes"` } +type QueryModAuditsResultType struct { + Count int `json:"count"` + Audits []*ModAudit `json:"audits"` +} + type QueryNotificationsInput struct { Page int `json:"page"` PerPage int `json:"per_page"` @@ -763,6 +912,8 @@ type QueryNotificationsResult struct { type QueryPerformersResultType struct { Count int `json:"count"` Performers []*Performer `json:"performers"` + // Search facets, only available for searchPerformer queries + Facets *PerformerSearchFacets `json:"facets,omitempty"` } type QueryScenesResultType struct { @@ -770,6 +921,11 @@ type QueryScenesResultType struct { Scenes []*Scene `json:"scenes"` } +type QuerySiteCategoriesResultType struct { + Count int `json:"count"` + SiteCategories []*SiteCategory `json:"site_categories"` +} + type QuerySitesResultType struct { Count int `json:"count"` Sites []*Site `json:"sites"` @@ -942,12 +1098,13 @@ type SceneEditInput struct { } type SceneQueryInput struct { - // Filter to search title and details - assumes like query unless quoted Text *string `json:"text,omitempty"` // Filter to search title - assumes like query unless quoted Title *string `json:"title,omitempty"` // Filter to search urls - assumes like query unless quoted URL *string `json:"url,omitempty"` + // Filter by scene code + Code *StringCriterionInput `json:"code,omitempty"` // Filter by date Date *DateCriterionInput `json:"date,omitempty"` // Filter by production date @@ -999,8 +1156,35 @@ type Site struct { Regex *string `json:"regex,omitempty"` ValidTypes []ValidSiteTypeEnum `json:"valid_types"` Icon string `json:"icon"` - Created time.Time `json:"created"` - Updated time.Time `json:"updated"` + Category *SiteCategory `json:"category,omitempty"` + // Whether links for this site are highlighted on entity pages, in addition to being listed in the links section + Highlighted bool `json:"highlighted"` + Created time.Time `json:"created"` + Updated time.Time `json:"updated"` +} + +type SiteCategory struct { + ID int `json:"id"` + Name string `json:"name"` + Description *string `json:"description,omitempty"` + SortOrder int `json:"sort_order"` +} + +type SiteCategoryCreateInput struct { + Name string `json:"name"` + Description *string `json:"description,omitempty"` + SortOrder *int `json:"sort_order,omitempty"` +} + +type SiteCategoryDestroyInput struct { + ID int `json:"id"` +} + +type SiteCategoryUpdateInput struct { + ID int `json:"id"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + SortOrder *int `json:"sort_order,omitempty"` } type SiteCreateInput struct { @@ -1009,12 +1193,24 @@ type SiteCreateInput struct { URL *string `json:"url,omitempty"` Regex *string `json:"regex,omitempty"` ValidTypes []ValidSiteTypeEnum `json:"valid_types"` + CategoryID *int `json:"category_id,omitempty"` + Highlighted bool `json:"highlighted"` + // Base64 data URL of the favicon to store. Empty string clears it, null leaves it unchanged. + Favicon *string `json:"favicon,omitempty"` } type SiteDestroyInput struct { ID string `json:"id"` } +// A favicon candidate discovered for a site URL. +type SiteFavicon struct { + // Source URL the icon was found at. + URL string `json:"url"` + // Base64 data URL of the downloaded icon. + Image string `json:"image"` +} + type SiteUpdateInput struct { ID string `json:"id"` Name string `json:"name"` @@ -1022,6 +1218,10 @@ type SiteUpdateInput struct { URL *string `json:"url,omitempty"` Regex *string `json:"regex,omitempty"` ValidTypes []ValidSiteTypeEnum `json:"valid_types"` + CategoryID *int `json:"category_id,omitempty"` + Highlighted bool `json:"highlighted"` + // Base64 data URL of the favicon to store. Empty string clears it, null leaves it unchanged. + Favicon *string `json:"favicon,omitempty"` } type StashBoxConfig struct { @@ -1051,6 +1251,7 @@ type Studio struct { Urls []*URL `json:"urls"` Parent *Studio `json:"parent,omitempty"` ChildStudios []*Studio `json:"child_studios"` + SubStudios *QueryStudiosResultType `json:"sub_studios"` Images []*Image `json:"images"` Deleted bool `json:"deleted"` IsFavorite bool `json:"is_favorite"` @@ -1240,6 +1441,19 @@ type URLInput struct { SiteID string `json:"site_id"` } +type UnreadNotificationCount struct { + Total int `json:"total"` + Urgent int `json:"urgent"` +} + +type UpdateEditCommentInput struct { + // ID of the comment to edit + ID string `json:"id"` + Comment string `json:"comment"` + // Reason for the edit, recorded in the moderation audit log + Reason *string `json:"reason,omitempty"` +} + type UpdatedEdit struct { Edit *Edit `json:"edit"` } @@ -1295,13 +1509,20 @@ type UserDestroyInput struct { } type UserEditCount struct { - Accepted int `json:"accepted"` - Rejected int `json:"rejected"` - Pending int `json:"pending"` - ImmediateAccepted int `json:"immediate_accepted"` - ImmediateRejected int `json:"immediate_rejected"` - Failed int `json:"failed"` - Canceled int `json:"canceled"` + Accepted int `json:"accepted"` + Rejected int `json:"rejected"` + Pending int `json:"pending"` + ImmediateAccepted int `json:"immediate_accepted"` + ImmediateRejected int `json:"immediate_rejected"` + Failed int `json:"failed"` + Canceled int `json:"canceled"` + AcceptedBot int `json:"accepted_bot"` + RejectedBot int `json:"rejected_bot"` + PendingBot int `json:"pending_bot"` + ImmediateAcceptedBot int `json:"immediate_accepted_bot"` + ImmediateRejectedBot int `json:"immediate_rejected_bot"` + FailedBot int `json:"failed_bot"` + CanceledBot int `json:"canceled_bot"` } type UserQueryInput struct { @@ -2172,6 +2393,65 @@ func (e HairColorEnum) MarshalJSON() ([]byte, error) { return buf.Bytes(), nil } +type ModAuditActionEnum string + +const ( + ModAuditActionEnumEditDelete ModAuditActionEnum = "EDIT_DELETE" + ModAuditActionEnumEditAmendment ModAuditActionEnum = "EDIT_AMENDMENT" + ModAuditActionEnumEditCommentUpdate ModAuditActionEnum = "EDIT_COMMENT_UPDATE" + ModAuditActionEnumEditCommentHide ModAuditActionEnum = "EDIT_COMMENT_HIDE" +) + +var AllModAuditActionEnum = []ModAuditActionEnum{ + ModAuditActionEnumEditDelete, + ModAuditActionEnumEditAmendment, + ModAuditActionEnumEditCommentUpdate, + ModAuditActionEnumEditCommentHide, +} + +func (e ModAuditActionEnum) IsValid() bool { + switch e { + case ModAuditActionEnumEditDelete, ModAuditActionEnumEditAmendment, ModAuditActionEnumEditCommentUpdate, ModAuditActionEnumEditCommentHide: + return true + } + return false +} + +func (e ModAuditActionEnum) String() string { + return string(e) +} + +func (e *ModAuditActionEnum) UnmarshalGQL(v any) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = ModAuditActionEnum(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid ModAuditActionEnum", str) + } + return nil +} + +func (e ModAuditActionEnum) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +func (e *ModAuditActionEnum) UnmarshalJSON(b []byte) error { + s, err := strconv.Unquote(string(b)) + if err != nil { + return err + } + return e.UnmarshalGQL(s) +} + +func (e ModAuditActionEnum) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + e.MarshalGQL(&buf) + return buf.Bytes(), nil +} + type NotificationEnum string const ( @@ -2186,6 +2466,7 @@ const ( NotificationEnumCommentVotedEdit NotificationEnum = "COMMENT_VOTED_EDIT" NotificationEnumUpdatedEdit NotificationEnum = "UPDATED_EDIT" NotificationEnumFingerprintedSceneEdit NotificationEnum = "FINGERPRINTED_SCENE_EDIT" + NotificationEnumFingerprintMoved NotificationEnum = "FINGERPRINT_MOVED" ) var AllNotificationEnum = []NotificationEnum{ @@ -2200,11 +2481,12 @@ var AllNotificationEnum = []NotificationEnum{ NotificationEnumCommentVotedEdit, NotificationEnumUpdatedEdit, NotificationEnumFingerprintedSceneEdit, + NotificationEnumFingerprintMoved, } func (e NotificationEnum) IsValid() bool { switch e { - case NotificationEnumFavoritePerformerScene, NotificationEnumFavoritePerformerEdit, NotificationEnumFavoriteStudioScene, NotificationEnumFavoriteStudioEdit, NotificationEnumCommentOwnEdit, NotificationEnumDownvoteOwnEdit, NotificationEnumFailedOwnEdit, NotificationEnumCommentCommentedEdit, NotificationEnumCommentVotedEdit, NotificationEnumUpdatedEdit, NotificationEnumFingerprintedSceneEdit: + case NotificationEnumFavoritePerformerScene, NotificationEnumFavoritePerformerEdit, NotificationEnumFavoriteStudioScene, NotificationEnumFavoriteStudioEdit, NotificationEnumCommentOwnEdit, NotificationEnumDownvoteOwnEdit, NotificationEnumFailedOwnEdit, NotificationEnumCommentCommentedEdit, NotificationEnumCommentVotedEdit, NotificationEnumUpdatedEdit, NotificationEnumFingerprintedSceneEdit, NotificationEnumFingerprintMoved: return true } return false @@ -2245,6 +2527,61 @@ func (e NotificationEnum) MarshalJSON() ([]byte, error) { return buf.Bytes(), nil } +type NotificationLevel string + +const ( + NotificationLevelNormal NotificationLevel = "NORMAL" + NotificationLevelUrgent NotificationLevel = "URGENT" +) + +var AllNotificationLevel = []NotificationLevel{ + NotificationLevelNormal, + NotificationLevelUrgent, +} + +func (e NotificationLevel) IsValid() bool { + switch e { + case NotificationLevelNormal, NotificationLevelUrgent: + return true + } + return false +} + +func (e NotificationLevel) String() string { + return string(e) +} + +func (e *NotificationLevel) UnmarshalGQL(v any) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = NotificationLevel(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid NotificationLevel", str) + } + return nil +} + +func (e NotificationLevel) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +func (e *NotificationLevel) UnmarshalJSON(b []byte) error { + s, err := strconv.Unquote(string(b)) + if err != nil { + return err + } + return e.UnmarshalGQL(s) +} + +func (e NotificationLevel) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + e.MarshalGQL(&buf) + return buf.Bytes(), nil +} + type OperationEnum string const ( @@ -2314,6 +2651,7 @@ const ( PerformerSortEnumCareerStartYear PerformerSortEnum = "CAREER_START_YEAR" PerformerSortEnumDebut PerformerSortEnum = "DEBUT" PerformerSortEnumLastScene PerformerSortEnum = "LAST_SCENE" + PerformerSortEnumPopularity PerformerSortEnum = "POPULARITY" PerformerSortEnumCreatedAt PerformerSortEnum = "CREATED_AT" PerformerSortEnumUpdatedAt PerformerSortEnum = "UPDATED_AT" ) @@ -2326,13 +2664,14 @@ var AllPerformerSortEnum = []PerformerSortEnum{ PerformerSortEnumCareerStartYear, PerformerSortEnumDebut, PerformerSortEnumLastScene, + PerformerSortEnumPopularity, PerformerSortEnumCreatedAt, PerformerSortEnumUpdatedAt, } func (e PerformerSortEnum) IsValid() bool { switch e { - case PerformerSortEnumName, PerformerSortEnumBirthdate, PerformerSortEnumDeathdate, PerformerSortEnumSceneCount, PerformerSortEnumCareerStartYear, PerformerSortEnumDebut, PerformerSortEnumLastScene, PerformerSortEnumCreatedAt, PerformerSortEnumUpdatedAt: + case PerformerSortEnumName, PerformerSortEnumBirthdate, PerformerSortEnumDeathdate, PerformerSortEnumSceneCount, PerformerSortEnumCareerStartYear, PerformerSortEnumDebut, PerformerSortEnumLastScene, PerformerSortEnumPopularity, PerformerSortEnumCreatedAt, PerformerSortEnumUpdatedAt: return true } return false @@ -2376,11 +2715,12 @@ func (e PerformerSortEnum) MarshalJSON() ([]byte, error) { type RoleEnum string const ( - RoleEnumRead RoleEnum = "READ" - RoleEnumVote RoleEnum = "VOTE" - RoleEnumEdit RoleEnum = "EDIT" - RoleEnumModify RoleEnum = "MODIFY" - RoleEnumAdmin RoleEnum = "ADMIN" + RoleEnumRead RoleEnum = "READ" + RoleEnumVote RoleEnum = "VOTE" + RoleEnumEdit RoleEnum = "EDIT" + RoleEnumModify RoleEnum = "MODIFY" + RoleEnumModerate RoleEnum = "MODERATE" + RoleEnumAdmin RoleEnum = "ADMIN" // May generate invites without tokens RoleEnumInvite RoleEnum = "INVITE" // May grant and rescind invite tokens and resind invite keys @@ -2395,6 +2735,7 @@ var AllRoleEnum = []RoleEnum{ RoleEnumVote, RoleEnumEdit, RoleEnumModify, + RoleEnumModerate, RoleEnumAdmin, RoleEnumInvite, RoleEnumManageInvites, @@ -2405,7 +2746,7 @@ var AllRoleEnum = []RoleEnum{ func (e RoleEnum) IsValid() bool { switch e { - case RoleEnumRead, RoleEnumVote, RoleEnumEdit, RoleEnumModify, RoleEnumAdmin, RoleEnumInvite, RoleEnumManageInvites, RoleEnumBot, RoleEnumReadOnly, RoleEnumEditTags: + case RoleEnumRead, RoleEnumVote, RoleEnumEdit, RoleEnumModify, RoleEnumModerate, RoleEnumAdmin, RoleEnumInvite, RoleEnumManageInvites, RoleEnumBot, RoleEnumReadOnly, RoleEnumEditTags: return true } return false @@ -2449,24 +2790,28 @@ func (e RoleEnum) MarshalJSON() ([]byte, error) { type SceneSortEnum string const ( - SceneSortEnumTitle SceneSortEnum = "TITLE" - SceneSortEnumDate SceneSortEnum = "DATE" - SceneSortEnumTrending SceneSortEnum = "TRENDING" - SceneSortEnumCreatedAt SceneSortEnum = "CREATED_AT" - SceneSortEnumUpdatedAt SceneSortEnum = "UPDATED_AT" + SceneSortEnumTitle SceneSortEnum = "TITLE" + SceneSortEnumDate SceneSortEnum = "DATE" + SceneSortEnumDuration SceneSortEnum = "DURATION" + SceneSortEnumTrending SceneSortEnum = "TRENDING" + SceneSortEnumPopularity SceneSortEnum = "POPULARITY" + SceneSortEnumCreatedAt SceneSortEnum = "CREATED_AT" + SceneSortEnumUpdatedAt SceneSortEnum = "UPDATED_AT" ) var AllSceneSortEnum = []SceneSortEnum{ SceneSortEnumTitle, SceneSortEnumDate, + SceneSortEnumDuration, SceneSortEnumTrending, + SceneSortEnumPopularity, SceneSortEnumCreatedAt, SceneSortEnumUpdatedAt, } func (e SceneSortEnum) IsValid() bool { switch e { - case SceneSortEnumTitle, SceneSortEnumDate, SceneSortEnumTrending, SceneSortEnumCreatedAt, SceneSortEnumUpdatedAt: + case SceneSortEnumTitle, SceneSortEnumDate, SceneSortEnumDuration, SceneSortEnumTrending, SceneSortEnumPopularity, SceneSortEnumCreatedAt, SceneSortEnumUpdatedAt: return true } return false diff --git a/pkg/stashbox/scene.go b/pkg/stashbox/scene.go index 1af10c91d4..0d0ed01df1 100644 --- a/pkg/stashbox/scene.go +++ b/pkg/stashbox/scene.go @@ -191,11 +191,7 @@ func (c Client) sceneFragmentToScrapedScene(ctx context.Context, s *graphql.Scen } if s.Studio != nil { - var err error - ss.Studio, err = c.resolveStudio(ctx, s.Studio) - if err != nil { - return nil, err - } + ss.Studio = studioFragmentToScrapedStudio(*s.Studio) } for _, p := range s.Performers { diff --git a/pkg/stashbox/studio.go b/pkg/stashbox/studio.go index 8934972f25..ee69bc2d50 100644 --- a/pkg/stashbox/studio.go +++ b/pkg/stashbox/studio.go @@ -9,28 +9,6 @@ import ( "github.com/stashapp/stash/pkg/stashbox/graphql" ) -func (c Client) resolveStudio(ctx context.Context, s *graphql.StudioFragment) (*models.ScrapedStudio, error) { - scraped := studioFragmentToScrapedStudio(*s) - - if s.Parent != nil { - parentStudio, err := c.client.FindStudio(ctx, &s.Parent.ID, nil) - if err != nil { - return nil, err - } - - if parentStudio.FindStudio == nil { - return scraped, nil - } - - scraped.Parent, err = c.resolveStudio(ctx, parentStudio.FindStudio) - if err != nil { - return nil, err - } - } - - return scraped, nil -} - func (c Client) FindStudio(ctx context.Context, query string) (*models.ScrapedStudio, error) { var studio *graphql.FindStudio @@ -49,10 +27,7 @@ func (c Client) FindStudio(ctx context.Context, query string) (*models.ScrapedSt var ret *models.ScrapedStudio if studio.FindStudio != nil { - ret, err = c.resolveStudio(ctx, studio.FindStudio) - if err != nil { - return nil, err - } + ret = studioFragmentToScrapedStudio(*studio.FindStudio) } return ret, nil @@ -81,5 +56,15 @@ func studioFragmentToScrapedStudio(s graphql.StudioFragment) *models.ScrapedStud st.Image = &st.Images[0] } + if s.Parent != nil { + st.Parent = studioFragmentToScrapedStudio(graphql.StudioFragment{ + Name: s.Parent.Name, + ID: s.Parent.ID, + Aliases: s.Parent.Aliases, + Urls: s.Parent.Urls, + Images: s.Parent.Images, + }) + } + return st }