Remove deprecated graphql fields (#4064)

* Remove deprecated list*Scrapers queries
* Remove other deprecated query resolvers
* Remove deprecated config fields
* Remove deprecated gallery fields
* Remove deprecated image fields
* Remove deprecated movie fields
* Remove deprecated performer fields
* Document scrape function issue
* Remove deprecated studio fields
* Remove deprecated scan input fields
* Remove deprecated scene fields
* Remove deprecated fields from filters
* Remove scene.file_mod_time
This commit is contained in:
WithoutPants 2023-10-17 11:59:35 +11:00 committed by GitHub
parent a9ab1fcca7
commit b6714fafba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
66 changed files with 101 additions and 1223 deletions

View file

@ -42,9 +42,6 @@ fragment ConfigGeneralData on ConfigGeneralResult {
excludes
imageExcludes
customPerformerImageLocation
scraperUserAgent
scraperCertCheck
scraperCDPPath
stashBoxes {
name
endpoint
@ -139,8 +136,6 @@ fragment ScraperSourceData on ScraperSource {
fragment ConfigDefaultSettingsData on ConfigDefaultSettingsResult {
scan {
useFileMetadata
stripFileExtension
scanGenerateCovers
scanGeneratePreviews
scanGenerateImagePreviews

View file

@ -20,6 +20,5 @@ fragment MovieData on Movie {
scenes {
id
title
path
}
}

View file

@ -1,6 +1,5 @@
fragment PerformerData on Performer {
id
checksum
name
disambiguation
url

View file

@ -1,3 +0,0 @@
query ScrapeFreeonesPerformers($q: String!) {
scrapeFreeonesPerformerList(query: $q)
}

View file

@ -1,5 +1,5 @@
query ListPerformerScrapers {
listPerformerScrapers {
listScrapers(types: [PERFORMER]) {
id
name
performer {
@ -10,7 +10,7 @@ query ListPerformerScrapers {
}
query ListSceneScrapers {
listSceneScrapers {
listScrapers(types: [SCENE]) {
id
name
scene {
@ -21,7 +21,7 @@ query ListSceneScrapers {
}
query ListGalleryScrapers {
listGalleryScrapers {
listScrapers(types: [GALLERY]) {
id
name
gallery {
@ -32,7 +32,7 @@ query ListGalleryScrapers {
}
query ListMovieScrapers {
listMovieScrapers {
listScrapers(types: [MOVIE]) {
id
name
movie {

View file

@ -109,14 +109,6 @@ type Query {
"List available scrapers"
listScrapers(types: [ScrapeContentType!]!): [Scraper!]!
listPerformerScrapers: [Scraper!]!
@deprecated(reason: "Use listScrapers(types: [PERFORMER])")
listSceneScrapers: [Scraper!]!
@deprecated(reason: "Use listScrapers(types: [SCENE])")
listGalleryScrapers: [Scraper!]!
@deprecated(reason: "Use listScrapers(types: [GALLERY])")
listMovieScrapers: [Scraper!]!
@deprecated(reason: "Use listScrapers(types: [MOVIE])")
"Scrape for a single scene"
scrapeSingleScene(
@ -170,27 +162,6 @@ type Query {
"Scrapes a complete movie record based on a URL"
scrapeMovieURL(url: String!): ScrapedMovie
"Scrape a list of performers based on name"
scrapePerformerList(scraper_id: ID!, query: String!): [ScrapedPerformer!]!
@deprecated(reason: "use scrapeSinglePerformer")
"Scrapes a complete performer record based on a scrapePerformerList result"
scrapePerformer(
scraper_id: ID!
scraped_performer: ScrapedPerformerInput!
): ScrapedPerformer @deprecated(reason: "use scrapeSinglePerformer")
"Scrapes a complete scene record based on an existing scene"
scrapeScene(scraper_id: ID!, scene: SceneUpdateInput!): ScrapedScene
@deprecated(reason: "use scrapeSingleScene")
"Scrapes a complete gallery record based on an existing gallery"
scrapeGallery(scraper_id: ID!, gallery: GalleryUpdateInput!): ScrapedGallery
@deprecated(reason: "use scrapeSingleGallery")
"Scrape a list of performers from a query"
scrapeFreeonesPerformerList(query: String!): [String!]!
@deprecated(
reason: "use scrapeSinglePerformer with scraper_id = builtin_freeones"
)
# Plugins
"List loaded plugins"
plugins: [Plugin!]
@ -228,8 +199,7 @@ type Query {
allMovies: [Movie!]!
allTags: [Tag!]!
# @deprecated
allPerformers: [Performer!]!
allPerformers: [Performer!]! @deprecated(reason: "Use findPerformers instead")
# Get everything with minimal metadata

View file

@ -139,8 +139,6 @@ input ConfigGeneralInput {
password: String
"Maximum session cookie age"
maxSessionAge: Int
"Comma separated list of proxies to allow traffic from"
trustedProxies: [String!] @deprecated(reason: "no longer supported")
"Name of the log file"
logFile: String
"Whether to also output to stderr"
@ -165,21 +163,6 @@ input ConfigGeneralInput {
imageExcludes: [String!]
"Custom Performer Image Location"
customPerformerImageLocation: String
"Scraper user agent string"
scraperUserAgent: String
@deprecated(
reason: "use mutation ConfigureScraping(input: ConfigScrapingInput) instead"
)
"Scraper CDP path. Path to chrome executable or remote address"
scraperCDPPath: String
@deprecated(
reason: "use mutation ConfigureScraping(input: ConfigScrapingInput) instead"
)
"Whether the scraper should check for invalid certificates"
scraperCertCheck: Boolean
@deprecated(
reason: "use mutation ConfigureScraping(input: ConfigScrapingInput) instead"
)
"Stash-box instances used for tagging"
stashBoxes: [StashBoxInput!]
"Python path - resolved using path if unset"
@ -269,8 +252,6 @@ type ConfigGeneralResult {
password: String!
"Maximum session cookie age"
maxSessionAge: Int!
"Comma separated list of proxies to allow traffic from"
trustedProxies: [String!] @deprecated(reason: "no longer supported")
"Name of the log file"
logFile: String
"Whether to also output to stderr"
@ -295,15 +276,6 @@ type ConfigGeneralResult {
imageExcludes: [String!]!
"Custom Performer Image Location"
customPerformerImageLocation: String
"Scraper user agent string"
scraperUserAgent: String
@deprecated(reason: "use ConfigResult.scraping instead")
"Scraper CDP path. Path to chrome executable or remote address"
scraperCDPPath: String
@deprecated(reason: "use ConfigResult.scraping instead")
"Whether the scraper should check for invalid certificates"
scraperCertCheck: Boolean!
@deprecated(reason: "use ConfigResult.scraping instead")
"Stash-box instances used for tagging"
stashBoxes: [StashBox!]!
"Python path - resolved using path if unset"
@ -388,9 +360,6 @@ input ConfigInterfaceInput {
"Interface language"
language: String
"Slideshow Delay"
slideshowDelay: Int @deprecated(reason: "Use imageLightbox.slideshowDelay")
imageLightbox: ConfigImageLightboxInput
"Set to true to disable creating new objects via the dropdown menus"
@ -461,15 +430,10 @@ type ConfigInterfaceResult {
"Interface language"
language: String
"Slideshow Delay"
slideshowDelay: Int @deprecated(reason: "Use imageLightbox.slideshowDelay")
imageLightbox: ConfigImageLightboxResult!
"Fields are true if creating via dropdown menus are disabled"
disableDropdownCreate: ConfigDisableDropdownCreate!
disabledDropdownCreate: ConfigDisableDropdownCreate!
@deprecated(reason: "Use disableDropdownCreate")
"Handy Connection Key"
handyKey: String

View file

@ -98,8 +98,6 @@ input PerformerFilterType {
country: StringCriterionInput
"Filter by eye color"
eye_color: StringCriterionInput
"Filter by height"
height: StringCriterionInput @deprecated(reason: "Use height_cm instead")
"Filter by height in cm"
height_cm: IntCriterionInput
"Filter by measurements"
@ -135,13 +133,7 @@ input PerformerFilterType {
"Filter by o count"
o_counter: IntCriterionInput
"Filter by StashID"
stash_id: StringCriterionInput
@deprecated(reason: "Use stash_id_endpoint instead")
"Filter by StashID"
stash_id_endpoint: StashIDCriterionInput
"Filter by rating"
rating: IntCriterionInput
@deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: IntCriterionInput
"Filter by url"
@ -169,8 +161,6 @@ input PerformerFilterType {
}
input SceneMarkerFilterType {
"Filter to only include scene markers with this tag"
tag_id: ID @deprecated(reason: "use tags filter instead")
"Filter to only include scene markers with these tags"
tags: HierarchicalMultiCriterionInput
"Filter to only include scene markers attached to a scene with these tags"
@ -212,9 +202,6 @@ input SceneFilterType {
path: StringCriterionInput
"Filter by file count"
file_count: IntCriterionInput
"Filter by rating"
rating: IntCriterionInput
@deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: IntCriterionInput
"Filter by organized"
@ -256,9 +243,6 @@ input SceneFilterType {
"Filter by performer count"
performer_count: IntCriterionInput
"Filter by StashID"
stash_id: StringCriterionInput
@deprecated(reason: "Use stash_id_endpoint instead")
"Filter by StashID"
stash_id_endpoint: StashIDCriterionInput
"Filter by url"
url: StringCriterionInput
@ -289,9 +273,6 @@ input MovieFilterType {
"Filter by duration (in seconds)"
duration: IntCriterionInput
"Filter by rating"
rating: IntCriterionInput
@deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: IntCriterionInput
"Filter to only include movies with this studio"
@ -320,15 +301,9 @@ input StudioFilterType {
"Filter to only include studios with this parent studio"
parents: MultiCriterionInput
"Filter by StashID"
stash_id: StringCriterionInput
@deprecated(reason: "Use stash_id_endpoint instead")
"Filter by StashID"
stash_id_endpoint: StashIDCriterionInput
"Filter to only include studios missing this property"
is_missing: String
"Filter by rating"
rating: IntCriterionInput
@deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: IntCriterionInput
"Filter by scene count"
@ -368,9 +343,6 @@ input GalleryFilterType {
is_missing: String
"Filter to include/exclude galleries that were created from zip"
is_zip: Boolean
"Filter by rating"
rating: IntCriterionInput
@deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: IntCriterionInput
"Filter by organized"
@ -476,9 +448,6 @@ input ImageFilterType {
path: StringCriterionInput
"Filter by file count"
file_count: IntCriterionInput
"Filter by rating"
rating: IntCriterionInput
@deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: IntCriterionInput
"Filter by date"

View file

@ -1,21 +1,16 @@
"Gallery type"
type Gallery {
id: ID!
checksum: String! @deprecated(reason: "Use files.fingerprints")
path: String @deprecated(reason: "Use files.path")
title: String
url: String @deprecated(reason: "Use urls")
urls: [String!]!
date: String
details: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
organized: Boolean!
created_at: Time!
updated_at: Time!
file_mod_time: Time @deprecated(reason: "Use files.mod_time")
files: [GalleryFile!]!
folder: Folder
@ -27,8 +22,6 @@ type Gallery {
tags: [Tag!]!
performers: [Performer!]!
"The images in the gallery"
images: [Image!]! @deprecated(reason: "Use findImages")
cover: Image
}
@ -38,8 +31,6 @@ input GalleryCreateInput {
urls: [String!]
date: String
details: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
organized: Boolean
@ -57,8 +48,6 @@ input GalleryUpdateInput {
urls: [String!]
date: String
details: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
organized: Boolean
@ -77,8 +66,6 @@ input BulkGalleryUpdateInput {
urls: BulkUpdateStrings
date: String
details: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
organized: Boolean

View file

@ -1,9 +1,6 @@
type Image {
id: ID!
checksum: String @deprecated(reason: "Use files.fingerprints")
title: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
url: String @deprecated(reason: "Use urls")
@ -11,13 +8,9 @@ type Image {
date: String
o_counter: Int
organized: Boolean!
path: String! @deprecated(reason: "Use files.path")
created_at: Time!
updated_at: Time!
file_mod_time: Time @deprecated(reason: "Use files.mod_time")
file: ImageFileType! @deprecated(reason: "Use visual_files")
files: [ImageFile!]! @deprecated(reason: "Use visual_files")
visual_files: [VisualFile!]!
paths: ImagePathsType! # Resolver
@ -44,8 +37,6 @@ input ImageUpdateInput {
clientMutationId: String
id: ID!
title: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
organized: Boolean
@ -65,8 +56,6 @@ input BulkImageUpdateInput {
clientMutationId: String
ids: [ID!]
title: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
organized: Boolean

View file

@ -75,19 +75,6 @@ input ScanMetaDataFilterInput {
input ScanMetadataInput {
paths: [String!]
# useFileMetadata is deprecated with the new file management system
# if this functionality is desired, then we can make a built in scraper instead.
"Set name, date, details from metadata (if present)"
useFileMetadata: Boolean @deprecated(reason: "Not implemented")
# stripFileExtension is deprecated since we no longer set the title from the
# filename - it is automatically returned if the object has no title. If this
# functionality is desired, then we could make this an option to not include
# the extension in the auto-generated title.
"Strip file extension from title"
stripFileExtension: Boolean @deprecated(reason: "Not implemented")
"Generate covers during scan"
scanGenerateCovers: Boolean
"Generate previews during scan"
@ -108,10 +95,6 @@ input ScanMetadataInput {
}
type ScanMetadataOptions {
"Set name, date, details from metadata (if present)"
useFileMetadata: Boolean! @deprecated(reason: "Not implemented")
"Strip file extension from title"
stripFileExtension: Boolean! @deprecated(reason: "Not implemented")
"Generate covers during scan"
scanGenerateCovers: Boolean!
"Generate previews during scan"

View file

@ -1,13 +1,10 @@
type Movie {
id: ID!
name: String!
checksum: String! @deprecated(reason: "MD5 hash of name, use name directly")
aliases: String
"Duration in seconds"
duration: Int
date: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
studio: Studio
@ -29,8 +26,6 @@ input MovieCreateInput {
"Duration in seconds"
duration: Int
date: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
studio_id: ID
@ -49,8 +44,6 @@ input MovieUpdateInput {
aliases: String
duration: Int
date: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
studio_id: ID
@ -66,8 +59,6 @@ input MovieUpdateInput {
input BulkMovieUpdateInput {
clientMutationId: String
ids: [ID!]
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
studio_id: ID

View file

@ -14,7 +14,6 @@ enum CircumisedEnum {
type Performer {
id: ID!
checksum: String @deprecated(reason: "Not used")
name: String!
disambiguation: String
url: String
@ -25,7 +24,6 @@ type Performer {
ethnicity: String
country: String
eye_color: String
height: String @deprecated(reason: "Use height_cm")
height_cm: Int
measurements: String
fake_tits: String
@ -34,7 +32,6 @@ type Performer {
career_length: String
tattoos: String
piercings: String
aliases: String @deprecated(reason: "Use alias_list")
alias_list: [String!]!
favorite: Boolean!
tags: [Tag!]!
@ -49,8 +46,6 @@ type Performer {
o_counter: Int # Resolver
scenes: [Scene!]!
stash_ids: [StashID!]!
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
details: String
@ -71,8 +66,6 @@ input PerformerCreateInput {
ethnicity: String
country: String
eye_color: String
# height must be parsable into an integer
height: String @deprecated(reason: "Use height_cm")
height_cm: Int
measurements: String
fake_tits: String
@ -81,7 +74,6 @@ input PerformerCreateInput {
career_length: String
tattoos: String
piercings: String
aliases: String @deprecated(reason: "Use alias_list")
alias_list: [String!]
twitter: String
instagram: String
@ -90,8 +82,6 @@ input PerformerCreateInput {
"This should be a URL or a base64 encoded data URL"
image: String
stash_ids: [StashIDInput!]
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
details: String
@ -111,8 +101,6 @@ input PerformerUpdateInput {
ethnicity: String
country: String
eye_color: String
# height must be parsable into an integer
height: String @deprecated(reason: "Use height_cm")
height_cm: Int
measurements: String
fake_tits: String
@ -121,7 +109,6 @@ input PerformerUpdateInput {
career_length: String
tattoos: String
piercings: String
aliases: String @deprecated(reason: "Use alias_list")
alias_list: [String!]
twitter: String
instagram: String
@ -130,8 +117,6 @@ input PerformerUpdateInput {
"This should be a URL or a base64 encoded data URL"
image: String
stash_ids: [StashIDInput!]
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
details: String
@ -156,8 +141,6 @@ input BulkPerformerUpdateInput {
ethnicity: String
country: String
eye_color: String
# height must be parsable into an integer
height: String @deprecated(reason: "Use height_cm")
height_cm: Int
measurements: String
fake_tits: String
@ -166,14 +149,11 @@ input BulkPerformerUpdateInput {
career_length: String
tattoos: String
piercings: String
aliases: String @deprecated(reason: "Use alias_list")
alias_list: BulkUpdateStrings
twitter: String
instagram: String
favorite: Boolean
tag_ids: BulkUpdateIds
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
details: String

View file

@ -15,7 +15,6 @@ type ScenePathsType {
stream: String # Resolver
webp: String # Resolver
vtt: String # Resolver
chapters_vtt: String @deprecated
sprite: String # Resolver
funscript: String # Resolver
interactive_heatmap: String # Resolver
@ -34,8 +33,6 @@ type VideoCaption {
type Scene {
id: ID!
checksum: String @deprecated(reason: "Use files.fingerprints")
oshash: String @deprecated(reason: "Use files.fingerprints")
title: String
code: String
details: String
@ -43,20 +40,15 @@ type Scene {
url: String @deprecated(reason: "Use urls")
urls: [String!]!
date: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
organized: Boolean!
o_counter: Int
path: String! @deprecated(reason: "Use files.path")
phash: String @deprecated(reason: "Use files.fingerprints")
interactive: Boolean!
interactive_speed: Int
captions: [VideoCaption!]
created_at: Time!
updated_at: Time!
file_mod_time: Time
"The last time play count was updated"
last_played_at: Time
"The time index a scene was left at"
@ -66,7 +58,6 @@ type Scene {
"The number ot times a scene has been played"
play_count: Int
file: SceneFileType! @deprecated(reason: "Use files")
files: [VideoFile!]!
paths: ScenePathsType! # Resolver
scene_markers: [SceneMarker!]!
@ -94,8 +85,6 @@ input SceneCreateInput {
url: String @deprecated(reason: "Use urls")
urls: [String!]
date: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
organized: Boolean
@ -126,8 +115,6 @@ input SceneUpdateInput {
url: String @deprecated(reason: "Use urls")
urls: [String!]
date: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
o_counter: Int
@ -172,8 +159,6 @@ input BulkSceneUpdateInput {
url: String @deprecated(reason: "Use urls")
urls: BulkUpdateStrings
date: String
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
organized: Boolean

View file

@ -1,7 +1,6 @@
type Studio {
id: ID!
name: String!
checksum: String! @deprecated(reason: "MD5 hash of name, use name directly")
url: String
parent_studio: Studio
child_studios: [Studio!]!
@ -15,8 +14,6 @@ type Studio {
performer_count(depth: Int): Int! # Resolver
movie_count(depth: Int): Int! # Resolver
stash_ids: [StashID!]!
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
details: String
@ -32,8 +29,6 @@ input StudioCreateInput {
"This should be a URL or a base64 encoded data URL"
image: String
stash_ids: [StashIDInput!]
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
details: String
@ -49,8 +44,6 @@ input StudioUpdateInput {
"This should be a URL or a base64 encoded data URL"
image: String
stash_ids: [StashIDInput!]
# rating expressed as 1-5
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
# rating expressed as 1-100
rating100: Int
details: String

View file

@ -153,40 +153,6 @@ func (t changesetTranslator) intPtrFromString(value *string) (*int, error) {
return &vv, nil
}
func (t changesetTranslator) ratingConversion(legacyValue *int, rating100Value *int) *int {
const (
legacyField = "rating"
rating100Field = "rating100"
)
legacyRating := t.optionalInt(legacyValue, legacyField)
if legacyRating.Set && !legacyRating.Null {
ret := models.Rating5To100(legacyRating.Value)
return &ret
}
o := t.optionalInt(rating100Value, rating100Field)
if o.Set && !o.Null {
return &o.Value
}
return nil
}
func (t changesetTranslator) optionalRatingConversion(legacyValue *int, rating100Value *int) models.OptionalInt {
const (
legacyField = "rating"
rating100Field = "rating100"
)
legacyRating := t.optionalInt(legacyValue, legacyField)
if legacyRating.Set && !legacyRating.Null {
legacyRating.Value = models.Rating5To100(legacyRating.Value)
return legacyRating
}
return t.optionalInt(rating100Value, rating100Field)
}
func (t changesetTranslator) optionalInt(value *int, field string) models.OptionalInt {
if !t.hasField(field) {
return models.OptionalInt{}

View file

@ -2,7 +2,6 @@ package api
import (
"context"
"time"
"github.com/stashapp/stash/internal/api/loaders"
"github.com/stashapp/stash/internal/manager/config"
@ -11,19 +10,6 @@ import (
"github.com/stashapp/stash/pkg/models"
)
func (r *galleryResolver) getPrimaryFile(ctx context.Context, obj *models.Gallery) (models.File, error) {
if obj.PrimaryFileID != nil {
f, err := loaders.From(ctx).FileByID.Load(*obj.PrimaryFileID)
if err != nil {
return nil, err
}
return f, nil
}
return nil, nil
}
func (r *galleryResolver) getFiles(ctx context.Context, obj *models.Gallery) ([]models.File, error) {
fileIDs, err := loaders.From(ctx).GalleryFiles.Load(obj.ID)
if err != nil {
@ -78,38 +64,6 @@ func (r *galleryResolver) Folder(ctx context.Context, obj *models.Gallery) (*mod
return ret, nil
}
func (r *galleryResolver) FileModTime(ctx context.Context, obj *models.Gallery) (*time.Time, error) {
f, err := r.getPrimaryFile(ctx, obj)
if err != nil {
return nil, err
}
if f != nil {
return &f.Base().ModTime, nil
}
return nil, nil
}
// Images is deprecated, slow and shouldn't be used
func (r *galleryResolver) Images(ctx context.Context, obj *models.Gallery) (ret []*models.Image, err error) {
if err := r.withReadTxn(ctx, func(ctx context.Context) error {
var err error
// #2376 - sort images by path
// doing this via Query is really slow, so stick with FindByGalleryID
ret, err = r.repository.Image.FindByGalleryID(ctx, obj.ID)
if err != nil {
return err
}
return err
}); err != nil {
return nil, err
}
return ret, nil
}
func (r *galleryResolver) Cover(ctx context.Context, obj *models.Gallery) (ret *models.Image, err error) {
if err := r.withReadTxn(ctx, func(ctx context.Context) error {
// Find cover image first
@ -130,26 +84,6 @@ func (r *galleryResolver) Date(ctx context.Context, obj *models.Gallery) (*strin
return nil, nil
}
func (r *galleryResolver) Checksum(ctx context.Context, obj *models.Gallery) (string, error) {
if !obj.Files.PrimaryLoaded() {
if err := r.withReadTxn(ctx, func(ctx context.Context) error {
return obj.LoadPrimaryFile(ctx, r.repository.File)
}); err != nil {
return "", err
}
}
return obj.PrimaryChecksum(), nil
}
func (r *galleryResolver) Rating(ctx context.Context, obj *models.Gallery) (*int, error) {
if obj.Rating != nil {
rating := models.Rating100To5(*obj.Rating)
return &rating, nil
}
return nil, nil
}
func (r *galleryResolver) Rating100(ctx context.Context, obj *models.Gallery) (*int, error) {
return obj.Rating, nil
}

View file

@ -3,7 +3,6 @@ package api
import (
"context"
"fmt"
"time"
"github.com/stashapp/stash/internal/api/loaders"
"github.com/stashapp/stash/internal/api/urlbuilders"
@ -18,19 +17,6 @@ func convertVisualFile(f models.File) (models.VisualFile, error) {
return vf, nil
}
func (r *imageResolver) getPrimaryFile(ctx context.Context, obj *models.Image) (models.VisualFile, error) {
if obj.PrimaryFileID != nil {
f, err := loaders.From(ctx).FileByID.Load(*obj.PrimaryFileID)
if err != nil {
return nil, err
}
return convertVisualFile(f)
}
return nil, nil
}
func (r *imageResolver) getFiles(ctx context.Context, obj *models.Image) ([]models.File, error) {
fileIDs, err := loaders.From(ctx).ImageFiles.Load(obj.ID)
if err != nil {
@ -46,26 +32,6 @@ func (r *imageResolver) Title(ctx context.Context, obj *models.Image) (*string,
return &ret, nil
}
func (r *imageResolver) File(ctx context.Context, obj *models.Image) (*ImageFileType, error) {
f, err := r.getPrimaryFile(ctx, obj)
if err != nil {
return nil, err
}
if f == nil {
return nil, nil
}
width := f.GetWidth()
height := f.GetHeight()
size := f.Base().Size
return &ImageFileType{
Size: int(size),
Width: width,
Height: height,
}, nil
}
func (r *imageResolver) VisualFiles(ctx context.Context, obj *models.Image) ([]models.VisualFile, error) {
files, err := r.getFiles(ctx, obj)
if err != nil {
@ -112,18 +78,6 @@ func (r *imageResolver) Files(ctx context.Context, obj *models.Image) ([]*models
return ret, nil
}
func (r *imageResolver) FileModTime(ctx context.Context, obj *models.Image) (*time.Time, error) {
f, err := r.getPrimaryFile(ctx, obj)
if err != nil {
return nil, err
}
if f != nil {
return &f.Base().ModTime, nil
}
return nil, nil
}
func (r *imageResolver) Paths(ctx context.Context, obj *models.Image) (*ImagePathsType, error) {
baseURL, _ := ctx.Value(BaseURLCtxKey).(string)
builder := urlbuilders.NewImageURLBuilder(baseURL, obj)
@ -151,14 +105,6 @@ func (r *imageResolver) Galleries(ctx context.Context, obj *models.Image) (ret [
return ret, firstError(errs)
}
func (r *imageResolver) Rating(ctx context.Context, obj *models.Image) (*int, error) {
if obj.Rating != nil {
rating := models.Rating100To5(*obj.Rating)
return &rating, nil
}
return nil, nil
}
func (r *imageResolver) Rating100(ctx context.Context, obj *models.Image) (*int, error) {
return obj.Rating, nil
}

View file

@ -5,15 +5,9 @@ import (
"github.com/stashapp/stash/internal/api/loaders"
"github.com/stashapp/stash/internal/api/urlbuilders"
"github.com/stashapp/stash/pkg/hash/md5"
"github.com/stashapp/stash/pkg/models"
)
func (r *movieResolver) Checksum(ctx context.Context, obj *models.Movie) (string, error) {
// generate checksum from movie name
return md5.FromString(obj.Name), nil
}
func (r *movieResolver) Date(ctx context.Context, obj *models.Movie) (*string, error) {
if obj.Date != nil {
result := obj.Date.String()
@ -22,14 +16,6 @@ func (r *movieResolver) Date(ctx context.Context, obj *models.Movie) (*string, e
return nil, nil
}
func (r *movieResolver) Rating(ctx context.Context, obj *models.Movie) (*int, error) {
if obj.Rating != nil {
rating := models.Rating100To5(*obj.Rating)
return &rating, nil
}
return nil, nil
}
func (r *movieResolver) Rating100(ctx context.Context, obj *models.Movie) (*int, error) {
return obj.Rating, nil
}

View file

@ -3,7 +3,6 @@ package api
import (
"context"
"strconv"
"strings"
"github.com/stashapp/stash/internal/api/loaders"
"github.com/stashapp/stash/internal/api/urlbuilders"
@ -13,24 +12,6 @@ import (
"github.com/stashapp/stash/pkg/performer"
)
// Checksum is deprecated
func (r *performerResolver) Checksum(ctx context.Context, obj *models.Performer) (*string, error) {
return nil, nil
}
func (r *performerResolver) Aliases(ctx context.Context, obj *models.Performer) (*string, error) {
if !obj.Aliases.Loaded() {
if err := r.withReadTxn(ctx, func(ctx context.Context) error {
return obj.LoadAliases(ctx, r.repository.Performer)
}); err != nil {
return nil, err
}
}
ret := strings.Join(obj.Aliases.List(), ", ")
return &ret, nil
}
func (r *performerResolver) AliasList(ctx context.Context, obj *models.Performer) ([]string, error) {
if !obj.Aliases.Loaded() {
if err := r.withReadTxn(ctx, func(ctx context.Context) error {
@ -186,14 +167,6 @@ func (r *performerResolver) StashIds(ctx context.Context, obj *models.Performer)
return stashIDsSliceToPtrSlice(obj.StashIDs.List()), nil
}
func (r *performerResolver) Rating(ctx context.Context, obj *models.Performer) (*int, error) {
if obj.Rating != nil {
rating := models.Rating100To5(*obj.Rating)
return &rating, nil
}
return nil, nil
}
func (r *performerResolver) Rating100(ctx context.Context, obj *models.Performer) (*int, error) {
return obj.Rating, nil
}

View file

@ -3,14 +3,11 @@ package api
import (
"context"
"fmt"
"strconv"
"time"
"github.com/stashapp/stash/internal/api/loaders"
"github.com/stashapp/stash/internal/api/urlbuilders"
"github.com/stashapp/stash/internal/manager"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/utils"
)
func convertVideoFile(f models.File) (*models.VideoFile, error) {
@ -68,18 +65,6 @@ func (r *sceneResolver) getFiles(ctx context.Context, obj *models.Scene) ([]*mod
return ret, nil
}
func (r *sceneResolver) FileModTime(ctx context.Context, obj *models.Scene) (*time.Time, error) {
f, err := r.getPrimaryFile(ctx, obj)
if err != nil {
return nil, err
}
if f != nil {
return &f.ModTime, nil
}
return nil, nil
}
func (r *sceneResolver) Date(ctx context.Context, obj *models.Scene) (*string, error) {
if obj.Date != nil {
result := obj.Date.String()
@ -88,31 +73,6 @@ func (r *sceneResolver) Date(ctx context.Context, obj *models.Scene) (*string, e
return nil, nil
}
// File is deprecated
func (r *sceneResolver) File(ctx context.Context, obj *models.Scene) (*models.SceneFileType, error) {
f, err := r.getPrimaryFile(ctx, obj)
if err != nil {
return nil, err
}
if f == nil {
return nil, nil
}
bitrate := int(f.BitRate)
size := strconv.FormatInt(f.Size, 10)
return &models.SceneFileType{
Size: &size,
Duration: handleFloat64(f.Duration),
VideoCodec: &f.VideoCodec,
AudioCodec: &f.AudioCodec,
Width: &f.Width,
Height: &f.Height,
Framerate: handleFloat64(f.FrameRate),
Bitrate: &bitrate,
}, nil
}
func (r *sceneResolver) Files(ctx context.Context, obj *models.Scene) ([]*models.VideoFile, error) {
files, err := r.getFiles(ctx, obj)
if err != nil {
@ -145,7 +105,6 @@ func (r *sceneResolver) Paths(ctx context.Context, obj *models.Scene) (*ScenePat
objHash := obj.GetHash(config.GetVideoFileNamingAlgorithm())
vttPath := builder.GetSpriteVTTURL(objHash)
spritePath := builder.GetSpriteURL(objHash)
chaptersVttPath := builder.GetChaptersVTTURL()
funscriptPath := builder.GetFunscriptURL()
captionBasePath := builder.GetCaptionURL()
interactiveHeatmap := builder.GetInteractiveHeatmapURL()
@ -156,7 +115,6 @@ func (r *sceneResolver) Paths(ctx context.Context, obj *models.Scene) (*ScenePat
Stream: &streamPath,
Webp: &webpPath,
Vtt: &vttPath,
ChaptersVtt: &chaptersVttPath,
Sprite: &spritePath,
Funscript: &funscriptPath,
InteractiveHeatmap: &interactiveHeatmap,
@ -285,30 +243,6 @@ func (r *sceneResolver) StashIds(ctx context.Context, obj *models.Scene) (ret []
return stashIDsSliceToPtrSlice(obj.StashIDs.List()), nil
}
func (r *sceneResolver) Phash(ctx context.Context, obj *models.Scene) (*string, error) {
f, err := r.getPrimaryFile(ctx, obj)
if err != nil {
return nil, err
}
if f == nil {
return nil, nil
}
val := f.Fingerprints.Get(models.FingerprintTypePhash)
if val == nil {
return nil, nil
}
phash, _ := val.(int64)
if phash != 0 {
hexval := utils.PhashToString(phash)
return &hexval, nil
}
return nil, nil
}
func (r *sceneResolver) SceneStreams(ctx context.Context, obj *models.Scene) ([]*manager.SceneStreamEndpoint, error) {
// load the primary file into the scene
_, err := r.getPrimaryFile(ctx, obj)

View file

@ -6,7 +6,6 @@ import (
"github.com/stashapp/stash/internal/api/loaders"
"github.com/stashapp/stash/internal/api/urlbuilders"
"github.com/stashapp/stash/pkg/gallery"
"github.com/stashapp/stash/pkg/hash/md5"
"github.com/stashapp/stash/pkg/image"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/movie"
@ -14,11 +13,6 @@ import (
"github.com/stashapp/stash/pkg/scene"
)
func (r *studioResolver) Checksum(ctx context.Context, obj *models.Studio) (string, error) {
// generate checksum from studio name
return md5.FromString(obj.Name), nil
}
func (r *studioResolver) ImagePath(ctx context.Context, obj *models.Studio) (*string, error) {
var hasImage bool
if err := r.withReadTxn(ctx, func(ctx context.Context) error {
@ -132,14 +126,6 @@ func (r *studioResolver) StashIds(ctx context.Context, obj *models.Studio) ([]*m
return stashIDsSliceToPtrSlice(obj.StashIDs.List()), nil
}
func (r *studioResolver) Rating(ctx context.Context, obj *models.Studio) (*int, error) {
if obj.Rating != nil {
rating := models.Rating100To5(*obj.Rating)
return &rating, nil
}
return nil, nil
}
func (r *studioResolver) Rating100(ctx context.Context, obj *models.Studio) (*int, error) {
return obj.Rating, nil
}

View file

@ -319,20 +319,6 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input ConfigGen
initCustomPerformerImages(*input.CustomPerformerImageLocation)
}
if input.ScraperUserAgent != nil {
c.Set(config.ScraperUserAgent, input.ScraperUserAgent)
refreshScraperCache = true
}
if input.ScraperCDPPath != nil {
c.Set(config.ScraperCDPPath, input.ScraperCDPPath)
refreshScraperCache = true
}
if input.ScraperCertCheck != nil {
c.Set(config.ScraperCertCheck, input.ScraperCertCheck)
}
if input.StashBoxes != nil {
if err := c.ValidateStashBoxes(input.StashBoxes); err != nil {
return nil, err
@ -424,11 +410,6 @@ func (r *mutationResolver) ConfigureInterface(ctx context.Context, input ConfigI
c.Set(config.Language, *input.Language)
}
// deprecated field
if input.SlideshowDelay != nil {
c.Set(config.ImageLightboxSlideshowDelay, *input.SlideshowDelay)
}
if input.ImageLightbox != nil {
options := input.ImageLightbox

View file

@ -44,7 +44,7 @@ func (r *mutationResolver) GalleryCreate(ctx context.Context, input GalleryCreat
newGallery.Title = input.Title
newGallery.Details = translator.string(input.Details)
newGallery.Rating = translator.ratingConversion(input.Rating, input.Rating100)
newGallery.Rating = input.Rating100
var err error
@ -183,7 +183,7 @@ func (r *mutationResolver) galleryUpdate(ctx context.Context, input models.Galle
}
updatedGallery.Details = translator.optionalString(input.Details, "details")
updatedGallery.Rating = translator.optionalRatingConversion(input.Rating, input.Rating100)
updatedGallery.Rating = translator.optionalInt(input.Rating100, "rating100")
updatedGallery.Organized = translator.optionalBool(input.Organized, "organized")
updatedGallery.Date, err = translator.optionalDate(input.Date, "date")
@ -258,7 +258,7 @@ func (r *mutationResolver) BulkGalleryUpdate(ctx context.Context, input BulkGall
updatedGallery := models.NewGalleryPartial()
updatedGallery.Details = translator.optionalString(input.Details, "details")
updatedGallery.Rating = translator.optionalRatingConversion(input.Rating, input.Rating100)
updatedGallery.Rating = translator.optionalInt(input.Rating100, "rating100")
updatedGallery.Organized = translator.optionalBool(input.Organized, "organized")
updatedGallery.URLs = translator.optionalURLsBulk(input.Urls, input.URL)

View file

@ -107,7 +107,7 @@ func (r *mutationResolver) imageUpdate(ctx context.Context, input ImageUpdateInp
updatedImage := models.NewImagePartial()
updatedImage.Title = translator.optionalString(input.Title, "title")
updatedImage.Rating = translator.optionalRatingConversion(input.Rating, input.Rating100)
updatedImage.Rating = translator.optionalInt(input.Rating100, "rating100")
updatedImage.Organized = translator.optionalBool(input.Organized, "organized")
updatedImage.Date, err = translator.optionalDate(input.Date, "date")
@ -203,7 +203,7 @@ func (r *mutationResolver) BulkImageUpdate(ctx context.Context, input BulkImageU
updatedImage := models.NewImagePartial()
updatedImage.Title = translator.optionalString(input.Title, "title")
updatedImage.Rating = translator.optionalRatingConversion(input.Rating, input.Rating100)
updatedImage.Rating = translator.optionalInt(input.Rating100, "rating100")
updatedImage.Organized = translator.optionalBool(input.Organized, "organized")
updatedImage.Date, err = translator.optionalDate(input.Date, "date")

View file

@ -35,7 +35,7 @@ func (r *mutationResolver) MovieCreate(ctx context.Context, input MovieCreateInp
newMovie.Name = input.Name
newMovie.Aliases = translator.string(input.Aliases)
newMovie.Duration = input.Duration
newMovie.Rating = translator.ratingConversion(input.Rating, input.Rating100)
newMovie.Rating = input.Rating100
newMovie.Director = translator.string(input.Director)
newMovie.Synopsis = translator.string(input.Synopsis)
newMovie.URL = translator.string(input.URL)
@ -122,7 +122,7 @@ func (r *mutationResolver) MovieUpdate(ctx context.Context, input MovieUpdateInp
updatedMovie.Name = translator.optionalString(input.Name, "name")
updatedMovie.Aliases = translator.optionalString(input.Aliases, "aliases")
updatedMovie.Duration = translator.optionalInt(input.Duration, "duration")
updatedMovie.Rating = translator.optionalRatingConversion(input.Rating, input.Rating100)
updatedMovie.Rating = translator.optionalInt(input.Rating100, "rating100")
updatedMovie.Director = translator.optionalString(input.Director, "director")
updatedMovie.Synopsis = translator.optionalString(input.Synopsis, "synopsis")
updatedMovie.URL = translator.optionalString(input.URL, "url")
@ -198,7 +198,7 @@ func (r *mutationResolver) BulkMovieUpdate(ctx context.Context, input BulkMovieU
// Populate movie from the input
updatedMovie := models.NewMoviePartial()
updatedMovie.Rating = translator.optionalRatingConversion(input.Rating, input.Rating100)
updatedMovie.Rating = translator.optionalInt(input.Rating100, "rating100")
updatedMovie.Director = translator.optionalString(input.Director, "director")
updatedMovie.StudioID, err = translator.optionalIntFromString(input.StudioID, "studio_id")

View file

@ -49,9 +49,10 @@ func (r *mutationResolver) PerformerCreate(ctx context.Context, input models.Per
newPerformer.Twitter = translator.string(input.Twitter)
newPerformer.Instagram = translator.string(input.Instagram)
newPerformer.Favorite = translator.bool(input.Favorite)
newPerformer.Rating = translator.ratingConversion(input.Rating, input.Rating100)
newPerformer.Rating = input.Rating100
newPerformer.Details = translator.string(input.Details)
newPerformer.HairColor = translator.string(input.HairColor)
newPerformer.Height = input.HeightCm
newPerformer.Weight = input.Weight
newPerformer.IgnoreAutoTag = translator.bool(input.IgnoreAutoTag)
newPerformer.StashIDs = models.NewRelatedStashIDs(input.StashIds)
@ -67,21 +68,9 @@ func (r *mutationResolver) PerformerCreate(ctx context.Context, input models.Per
return nil, fmt.Errorf("converting death date: %w", err)
}
// prefer height_cm over height
if input.HeightCm != nil {
newPerformer.Height = input.HeightCm
} else {
newPerformer.Height, err = translator.intPtrFromString(input.Height)
if err != nil {
return nil, fmt.Errorf("converting height: %w", err)
}
}
// prefer alias_list over aliases
if input.AliasList != nil {
newPerformer.Aliases = models.NewRelatedStrings(input.AliasList)
} else if input.Aliases != nil {
newPerformer.Aliases = models.NewRelatedStrings(stringslice.FromString(*input.Aliases, ","))
}
newPerformer.TagIDs, err = translator.relatedIds(input.TagIds)
@ -163,7 +152,7 @@ func (r *mutationResolver) PerformerUpdate(ctx context.Context, input models.Per
updatedPerformer.Twitter = translator.optionalString(input.Twitter, "twitter")
updatedPerformer.Instagram = translator.optionalString(input.Instagram, "instagram")
updatedPerformer.Favorite = translator.optionalBool(input.Favorite, "favorite")
updatedPerformer.Rating = translator.optionalRatingConversion(input.Rating, input.Rating100)
updatedPerformer.Rating = translator.optionalInt(input.Rating100, "rating100")
updatedPerformer.Details = translator.optionalString(input.Details, "details")
updatedPerformer.HairColor = translator.optionalString(input.HairColor, "hair_color")
updatedPerformer.Weight = translator.optionalInt(input.Weight, "weight")
@ -182,22 +171,11 @@ func (r *mutationResolver) PerformerUpdate(ctx context.Context, input models.Per
// prefer height_cm over height
if translator.hasField("height_cm") {
updatedPerformer.Height = translator.optionalInt(input.HeightCm, "height_cm")
} else if translator.hasField("height") {
updatedPerformer.Height, err = translator.optionalIntFromString(input.Height, "height")
if err != nil {
return nil, fmt.Errorf("converting height: %w", err)
}
}
// prefer alias_list over aliases
if translator.hasField("alias_list") {
updatedPerformer.Aliases = translator.updateStrings(input.AliasList, "alias_list")
} else if translator.hasField("aliases") {
var aliasList []string
if input.Aliases != nil {
aliasList = stringslice.FromString(*input.Aliases, ",")
}
updatedPerformer.Aliases = translator.updateStrings(aliasList, "aliases")
}
updatedPerformer.TagIDs, err = translator.updateIds(input.TagIds, "tag_ids")
@ -286,7 +264,7 @@ func (r *mutationResolver) BulkPerformerUpdate(ctx context.Context, input BulkPe
updatedPerformer.Twitter = translator.optionalString(input.Twitter, "twitter")
updatedPerformer.Instagram = translator.optionalString(input.Instagram, "instagram")
updatedPerformer.Favorite = translator.optionalBool(input.Favorite, "favorite")
updatedPerformer.Rating = translator.optionalRatingConversion(input.Rating, input.Rating100)
updatedPerformer.Rating = translator.optionalInt(input.Rating100, "rating100")
updatedPerformer.Details = translator.optionalString(input.Details, "details")
updatedPerformer.HairColor = translator.optionalString(input.HairColor, "hair_color")
updatedPerformer.Weight = translator.optionalInt(input.Weight, "weight")
@ -304,22 +282,11 @@ func (r *mutationResolver) BulkPerformerUpdate(ctx context.Context, input BulkPe
// prefer height_cm over height
if translator.hasField("height_cm") {
updatedPerformer.Height = translator.optionalInt(input.HeightCm, "height_cm")
} else if translator.hasField("height") {
updatedPerformer.Height, err = translator.optionalIntFromString(input.Height, "height")
if err != nil {
return nil, fmt.Errorf("converting height: %w", err)
}
}
// prefer alias_list over aliases
if translator.hasField("alias_list") {
updatedPerformer.Aliases = translator.updateStringsBulk(input.AliasList, "alias_list")
} else if translator.hasField("aliases") {
var aliasList []string
if input.Aliases != nil {
aliasList = stringslice.FromString(*input.Aliases, ",")
}
updatedPerformer.Aliases = translator.updateStrings(aliasList, "aliases")
}
updatedPerformer.TagIDs, err = translator.updateIdsBulk(input.TagIds, "tag_ids")

View file

@ -45,7 +45,7 @@ func (r *mutationResolver) SceneCreate(ctx context.Context, input models.SceneCr
newScene.Code = translator.string(input.Code)
newScene.Details = translator.string(input.Details)
newScene.Director = translator.string(input.Director)
newScene.Rating = translator.ratingConversion(input.Rating, input.Rating100)
newScene.Rating = input.Rating100
newScene.Organized = translator.bool(input.Organized)
newScene.StashIDs = models.NewRelatedStashIDs(input.StashIds)
@ -168,7 +168,7 @@ func scenePartialFromInput(input models.SceneUpdateInput, translator changesetTr
updatedScene.Code = translator.optionalString(input.Code, "code")
updatedScene.Details = translator.optionalString(input.Details, "details")
updatedScene.Director = translator.optionalString(input.Director, "director")
updatedScene.Rating = translator.optionalRatingConversion(input.Rating, input.Rating100)
updatedScene.Rating = translator.optionalInt(input.Rating100, "rating100")
updatedScene.OCounter = translator.optionalInt(input.OCounter, "o_counter")
updatedScene.PlayCount = translator.optionalInt(input.PlayCount, "play_count")
updatedScene.PlayDuration = translator.optionalFloat64(input.PlayDuration, "play_duration")
@ -321,7 +321,7 @@ func (r *mutationResolver) BulkSceneUpdate(ctx context.Context, input BulkSceneU
updatedScene.Code = translator.optionalString(input.Code, "code")
updatedScene.Details = translator.optionalString(input.Details, "details")
updatedScene.Director = translator.optionalString(input.Director, "director")
updatedScene.Rating = translator.optionalRatingConversion(input.Rating, input.Rating100)
updatedScene.Rating = translator.optionalInt(input.Rating100, "rating100")
updatedScene.Organized = translator.optionalBool(input.Organized, "organized")
updatedScene.Date, err = translator.optionalDate(input.Date, "date")

View file

@ -34,7 +34,7 @@ func (r *mutationResolver) StudioCreate(ctx context.Context, input models.Studio
newStudio.Name = input.Name
newStudio.URL = translator.string(input.URL)
newStudio.Rating = translator.ratingConversion(input.Rating, input.Rating100)
newStudio.Rating = input.Rating100
newStudio.Details = translator.string(input.Details)
newStudio.IgnoreAutoTag = translator.bool(input.IgnoreAutoTag)
newStudio.Aliases = models.NewRelatedStrings(input.Aliases)
@ -108,7 +108,7 @@ func (r *mutationResolver) StudioUpdate(ctx context.Context, input models.Studio
updatedStudio.Name = translator.optionalString(input.Name, "name")
updatedStudio.URL = translator.optionalString(input.URL, "url")
updatedStudio.Details = translator.optionalString(input.Details, "details")
updatedStudio.Rating = translator.optionalRatingConversion(input.Rating, input.Rating100)
updatedStudio.Rating = translator.optionalInt(input.Rating100, "rating100")
updatedStudio.IgnoreAutoTag = translator.optionalBool(input.IgnoreAutoTag, "ignore_auto_tag")
updatedStudio.Aliases = translator.updateStrings(input.Aliases, "aliases")
updatedStudio.StashIDs = translator.updateStashIDs(input.StashIds, "stash_ids")

View file

@ -79,9 +79,6 @@ func makeConfigGeneralResult() *ConfigGeneralResult {
customPerformerImageLocation := config.GetCustomPerformerImageLocation()
scraperUserAgent := config.GetScraperUserAgent()
scraperCDPPath := config.GetScraperCDPPath()
return &ConfigGeneralResult{
Stashes: config.GetStashPaths(),
DatabasePath: config.GetDatabasePath(),
@ -123,9 +120,6 @@ func makeConfigGeneralResult() *ConfigGeneralResult {
Excludes: config.GetExcludes(),
ImageExcludes: config.GetImageExcludes(),
CustomPerformerImageLocation: &customPerformerImageLocation,
ScraperUserAgent: &scraperUserAgent,
ScraperCertCheck: config.GetScraperCertCheck(),
ScraperCDPPath: &scraperCDPPath,
StashBoxes: config.GetStashBoxes(),
PythonPath: config.GetPythonPath(),
TranscodeInputArgs: config.GetTranscodeInputArgs(),
@ -161,7 +155,6 @@ func makeConfigInterfaceResult() *ConfigInterfaceResult {
scriptOffset := config.GetFunscriptOffset()
useStashHostedFunscript := config.GetUseStashHostedFunscript()
imageLightboxOptions := config.GetImageLightboxOptions()
// FIXME - misnamed output field means we have redundant fields
disableDropdownCreate := config.GetDisableDropdownCreate()
return &ConfigInterfaceResult{
@ -187,8 +180,6 @@ func makeConfigInterfaceResult() *ConfigInterfaceResult {
ImageLightbox: &imageLightboxOptions,
// FIXME - see above
DisabledDropdownCreate: disableDropdownCreate,
DisableDropdownCreate: disableDropdownCreate,
HandyKey: &handyKey,

View file

@ -21,70 +21,10 @@ func (r *queryResolver) ScrapeURL(ctx context.Context, url string, ty scraper.Sc
return r.scraperCache().ScrapeURL(ctx, url, ty)
}
// deprecated
func (r *queryResolver) ScrapeFreeonesPerformerList(ctx context.Context, query string) ([]string, error) {
content, err := r.scraperCache().ScrapeName(ctx, scraper.FreeonesScraperID, query, scraper.ScrapeContentTypePerformer)
if err != nil {
return nil, err
}
performers, err := marshalScrapedPerformers(content)
if err != nil {
return nil, err
}
var ret []string
for _, p := range performers {
if p.Name != nil {
ret = append(ret, *p.Name)
}
}
return ret, nil
}
func (r *queryResolver) ListScrapers(ctx context.Context, types []scraper.ScrapeContentType) ([]*scraper.Scraper, error) {
return r.scraperCache().ListScrapers(types), nil
}
func (r *queryResolver) ListPerformerScrapers(ctx context.Context) ([]*scraper.Scraper, error) {
return r.scraperCache().ListScrapers([]scraper.ScrapeContentType{scraper.ScrapeContentTypePerformer}), nil
}
func (r *queryResolver) ListSceneScrapers(ctx context.Context) ([]*scraper.Scraper, error) {
return r.scraperCache().ListScrapers([]scraper.ScrapeContentType{scraper.ScrapeContentTypeScene}), nil
}
func (r *queryResolver) ListGalleryScrapers(ctx context.Context) ([]*scraper.Scraper, error) {
return r.scraperCache().ListScrapers([]scraper.ScrapeContentType{scraper.ScrapeContentTypeGallery}), nil
}
func (r *queryResolver) ListMovieScrapers(ctx context.Context) ([]*scraper.Scraper, error) {
return r.scraperCache().ListScrapers([]scraper.ScrapeContentType{scraper.ScrapeContentTypeMovie}), nil
}
func (r *queryResolver) ScrapePerformerList(ctx context.Context, scraperID string, query string) ([]*models.ScrapedPerformer, error) {
if query == "" {
return nil, nil
}
content, err := r.scraperCache().ScrapeName(ctx, scraperID, query, scraper.ScrapeContentTypePerformer)
if err != nil {
return nil, err
}
return marshalScrapedPerformers(content)
}
func (r *queryResolver) ScrapePerformer(ctx context.Context, scraperID string, scrapedPerformer scraper.ScrapedPerformerInput) (*models.ScrapedPerformer, error) {
content, err := r.scraperCache().ScrapeFragment(ctx, scraperID, scraper.Input{Performer: &scrapedPerformer})
if err != nil {
return nil, err
}
return marshalScrapedPerformer(content)
}
func (r *queryResolver) ScrapePerformerURL(ctx context.Context, url string) (*models.ScrapedPerformer, error) {
content, err := r.scraperCache().ScrapeURL(ctx, url, scraper.ScrapeContentTypePerformer)
if err != nil {
@ -113,29 +53,6 @@ func (r *queryResolver) ScrapeSceneQuery(ctx context.Context, scraperID string,
return ret, nil
}
func (r *queryResolver) ScrapeScene(ctx context.Context, scraperID string, scene models.SceneUpdateInput) (*scraper.ScrapedScene, error) {
id, err := strconv.Atoi(scene.ID)
if err != nil {
return nil, fmt.Errorf("%w: scene.ID is not an integer: '%s'", ErrInput, scene.ID)
}
content, err := r.scraperCache().ScrapeID(ctx, scraperID, id, scraper.ScrapeContentTypeScene)
if err != nil {
return nil, err
}
ret, err := marshalScrapedScene(content)
if err != nil {
return nil, err
}
if ret != nil {
filterSceneTags([]*scraper.ScrapedScene{ret})
}
return ret, nil
}
// filterSceneTags removes tags matching excluded tag patterns from the provided scraped scenes
func filterSceneTags(scenes []*scraper.ScrapedScene) {
excludePatterns := manager.GetInstance().Config.GetScraperExcludeTagPatterns()
@ -199,20 +116,6 @@ func (r *queryResolver) ScrapeSceneURL(ctx context.Context, url string) (*scrape
return ret, nil
}
func (r *queryResolver) ScrapeGallery(ctx context.Context, scraperID string, gallery models.GalleryUpdateInput) (*scraper.ScrapedGallery, error) {
id, err := strconv.Atoi(gallery.ID)
if err != nil {
return nil, fmt.Errorf("%w: gallery id is not an integer: '%s'", ErrInput, gallery.ID)
}
content, err := r.scraperCache().ScrapeID(ctx, scraperID, id, scraper.ScrapeContentTypeGallery)
if err != nil {
return nil, err
}
return marshalScrapedGallery(content)
}
func (r *queryResolver) ScrapeGalleryURL(ctx context.Context, url string) (*scraper.ScrapedGallery, error) {
content, err := r.scraperCache().ScrapeURL(ctx, url, scraper.ScrapeContentTypeGallery)
if err != nil {
@ -241,6 +144,8 @@ func (r *queryResolver) getStashBoxClient(index int) (*stashbox.Client, error) {
return stashbox.NewClient(*boxes[index], r.stashboxRepository()), nil
}
// FIXME - in the following resolvers, we're processing the deprecated field and not processing the new endpoint input
func (r *queryResolver) ScrapeSingleScene(ctx context.Context, source scraper.Source, input ScrapeSingleSceneInput) ([]*scraper.ScrapedScene, error) {
var ret []*scraper.ScrapedScene
@ -378,6 +283,7 @@ func (r *queryResolver) ScrapeSinglePerformer(ctx context.Context, source scrape
}
return nil, ErrNotImplemented
// FIXME - we're relying on a deprecated field and not processing the endpoint input
} else if source.StashBoxIndex != nil {
client, err := r.getStashBoxClient(*source.StashBoxIndex)
if err != nil {

View file

@ -1,21 +1,9 @@
package api
import (
"math"
"github.com/stashapp/stash/pkg/models"
)
// #1572 - Inf and NaN values cause the JSON marshaller to fail
// Return nil for these values
func handleFloat64(v float64) *float64 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil
}
return &v
}
func stashIDsSliceToPtrSlice(v []models.StashID) []*models.StashID {
ret := make([]*models.StashID, len(v))
for i, vv := range v {

View file

@ -57,10 +57,6 @@ func (b SceneURLBuilder) GetScreenshotURL() string {
return b.BaseURL + "/scene/" + b.SceneID + "/screenshot?t=" + b.UpdatedAt
}
func (b SceneURLBuilder) GetChaptersVTTURL() string {
return b.BaseURL + "/scene/" + b.SceneID + "/vtt/chapter"
}
func (b SceneURLBuilder) GetFunscriptURL() string {
return b.BaseURL + "/scene/" + b.SceneID + "/funscript"
}

View file

@ -717,9 +717,9 @@ func (me *contentDirectoryService) getRatingScenes(paths []string, host string)
}
sceneFilter := &models.SceneFilterType{
Rating: &models.IntCriterionInput{
Rating100: &models.IntCriterionInput{
Modifier: models.CriterionModifierEquals,
Value: r,
Value: models.Rating5To100(r),
},
}

View file

@ -1,12 +1,6 @@
package config
type ScanMetadataOptions struct {
// Set name, date, details from metadata (if present)
// Deprecated: not implemented
UseFileMetadata bool `json:"useFileMetadata"`
// Strip file extension from title
// Deprecated: not implemented
StripFileExtension bool `json:"stripFileExtension"`
// Generate scene covers during scan
ScanGenerateCovers bool `json:"scanGenerateCovers"`
// Generate previews during scan

View file

@ -17,8 +17,6 @@ type GalleryFilterType struct {
IsMissing *string `json:"is_missing"`
// Filter to include/exclude galleries that were created from zip
IsZip *bool `json:"is_zip"`
// Filter by rating expressed as 1-5
Rating *IntCriterionInput `json:"rating"`
// Filter by rating expressed as 1-100
Rating100 *IntCriterionInput `json:"rating100"`
// Filter by organized
@ -62,7 +60,6 @@ type GalleryUpdateInput struct {
Urls []string `json:"urls"`
Date *string `json:"date"`
Details *string `json:"details"`
Rating *int `json:"rating"`
Rating100 *int `json:"rating100"`
Organized *bool `json:"organized"`
SceneIds []string `json:"scene_ids"`

View file

@ -14,8 +14,6 @@ type ImageFilterType struct {
Path *StringCriterionInput `json:"path"`
// Filter by file count
FileCount *IntCriterionInput `json:"file_count"`
// Filter by rating expressed as 1-5
Rating *IntCriterionInput `json:"rating"`
// Filter by rating expressed as 1-100
Rating100 *IntCriterionInput `json:"rating100"`
// Filter by date

View file

@ -221,12 +221,6 @@ func (s ScenePartial) UpdateInput(id int) SceneUpdateInput {
StashIds: stashIDs,
}
if s.Rating.Set && !s.Rating.Null {
// convert to 1-100 scale
rating := Rating100To5(s.Rating.Value)
ret.Rating = &rating
}
return ret
}

View file

@ -18,7 +18,6 @@ func TestScenePartial_UpdateInput(t *testing.T) {
director = "director"
url = "url"
date = "2001-02-03"
ratingLegacy = 4
rating100 = 80
organized = true
studioID = 2
@ -58,7 +57,6 @@ func TestScenePartial_UpdateInput(t *testing.T) {
Director: &director,
Urls: []string{url},
Date: &date,
Rating: &ratingLegacy,
Rating100: &rating100,
Organized: &organized,
StudioID: &studioIDStr,

View file

@ -6,8 +6,6 @@ type MovieFilterType struct {
Synopsis *StringCriterionInput `json:"synopsis"`
// Filter by duration (in seconds)
Duration *IntCriterionInput `json:"duration"`
// Filter by rating expressed as 1-5
Rating *IntCriterionInput `json:"rating"`
// Filter by rating expressed as 1-100
Rating100 *IntCriterionInput `json:"rating100"`
// Filter to only include movies with this studio

View file

@ -165,8 +165,6 @@ type PerformerFilterType struct {
StashID *StringCriterionInput `json:"stash_id"`
// Filter by StashID Endpoint
StashIDEndpoint *StashIDCriterionInput `json:"stash_id_endpoint"`
// Filter by rating expressed as 1-5
Rating *IntCriterionInput `json:"rating"`
// Filter by rating expressed as 1-100
Rating100 *IntCriterionInput `json:"rating100"`
// Filter by url
@ -220,7 +218,6 @@ type PerformerCreateInput struct {
// This should be a URL or a base64 encoded data URL
Image *string `json:"image"`
StashIds []StashID `json:"stash_ids"`
Rating *int `json:"rating"`
Rating100 *int `json:"rating100"`
Details *string `json:"details"`
DeathDate *string `json:"death_date"`
@ -257,7 +254,6 @@ type PerformerUpdateInput struct {
// This should be a URL or a base64 encoded data URL
Image *string `json:"image"`
StashIds []StashID `json:"stash_ids"`
Rating *int `json:"rating"`
Rating100 *int `json:"rating100"`
Details *string `json:"details"`
DeathDate *string `json:"death_date"`

View file

@ -29,8 +29,6 @@ type SceneFilterType struct {
Path *StringCriterionInput `json:"path"`
// Filter by file count
FileCount *IntCriterionInput `json:"file_count"`
// Filter by rating expressed as 1-5
Rating *IntCriterionInput `json:"rating"`
// Filter by rating expressed as 1-100
Rating100 *IntCriterionInput `json:"rating100"`
// Filter by organized
@ -128,7 +126,6 @@ type SceneCreateInput struct {
URL *string `json:"url"`
Urls []string `json:"urls"`
Date *string `json:"date"`
Rating *int `json:"rating"`
Rating100 *int `json:"rating100"`
Organized *bool `json:"organized"`
StudioID *string `json:"studio_id"`
@ -155,7 +152,6 @@ type SceneUpdateInput struct {
URL *string `json:"url"`
Urls []string `json:"urls"`
Date *string `json:"date"`
Rating *int `json:"rating"`
Rating100 *int `json:"rating100"`
OCounter *int `json:"o_counter"`
Organized *bool `json:"organized"`

View file

@ -14,8 +14,6 @@ type StudioFilterType struct {
StashIDEndpoint *StashIDCriterionInput `json:"stash_id_endpoint"`
// Filter to only include studios missing this property
IsMissing *string `json:"is_missing"`
// Filter by rating expressed as 1-5
Rating *IntCriterionInput `json:"rating"`
// Filter by rating expressed as 1-100
Rating100 *IntCriterionInput `json:"rating100"`
// Filter by scene count
@ -43,7 +41,6 @@ type StudioCreateInput struct {
// This should be a URL or a base64 encoded data URL
Image *string `json:"image"`
StashIds []StashID `json:"stash_ids"`
Rating *int `json:"rating"`
Rating100 *int `json:"rating100"`
Details *string `json:"details"`
Aliases []string `json:"aliases"`
@ -58,7 +55,6 @@ type StudioUpdateInput struct {
// This should be a URL or a base64 encoded data URL
Image *string `json:"image"`
StashIds []StashID `json:"stash_ids"`
Rating *int `json:"rating"`
Rating100 *int `json:"rating100"`
Details *string `json:"details"`
Aliases []string `json:"aliases"`

View file

@ -575,25 +575,6 @@ func boolCriterionHandler(c *bool, column string, addJoinFn func(f *filterBuilde
}
}
func rating5CriterionHandler(c *models.IntCriterionInput, column string, addJoinFn func(f *filterBuilder)) criterionHandlerFunc {
return func(ctx context.Context, f *filterBuilder) {
if c != nil {
// make a copy so we can adjust it
cc := *c
if cc.Value != 0 {
cc.Value = models.Rating5To100(cc.Value)
}
if cc.Value2 != nil {
val := models.Rating5To100(*cc.Value2)
cc.Value2 = &val
}
clause, args := getIntCriterionWhereClause(column, cc)
f.addWhere(clause, args...)
}
}
}
func dateCriterionHandler(c *models.DateCriterionInput, column string) criterionHandlerFunc {
return func(ctx context.Context, f *filterBuilder) {
if c != nil {

View file

@ -681,8 +681,6 @@ func (qb *GalleryStore) makeFilter(ctx context.Context, galleryFilter *models.Ga
query.handleCriterion(ctx, qb.galleryPathCriterionHandler(galleryFilter.Path))
query.handleCriterion(ctx, galleryFileCountCriterionHandler(qb, galleryFilter.FileCount))
query.handleCriterion(ctx, intCriterionHandler(galleryFilter.Rating100, "galleries.rating", nil))
// legacy rating handler
query.handleCriterion(ctx, rating5CriterionHandler(galleryFilter.Rating, "galleries.rating", nil))
query.handleCriterion(ctx, galleryURLsCriterionHandler(galleryFilter.URL))
query.handleCriterion(ctx, boolCriterionHandler(galleryFilter.Organized, "galleries.organized", nil))
query.handleCriterion(ctx, galleryIsMissingCriterionHandler(qb, galleryFilter.IsMissing))

View file

@ -1715,54 +1715,6 @@ func verifyGalleryQuery(t *testing.T, filter models.GalleryFilterType, verifyFn
})
}
func TestGalleryQueryLegacyRating(t *testing.T) {
const rating = 3
ratingCriterion := models.IntCriterionInput{
Value: rating,
Modifier: models.CriterionModifierEquals,
}
verifyGalleriesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierNotEquals
verifyGalleriesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierGreaterThan
verifyGalleriesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierLessThan
verifyGalleriesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierIsNull
verifyGalleriesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierNotNull
verifyGalleriesLegacyRating(t, ratingCriterion)
}
func verifyGalleriesLegacyRating(t *testing.T, ratingCriterion models.IntCriterionInput) {
withTxn(func(ctx context.Context) error {
sqb := db.Gallery
galleryFilter := models.GalleryFilterType{
Rating: &ratingCriterion,
}
galleries, _, err := sqb.Query(ctx, &galleryFilter, nil)
if err != nil {
t.Errorf("Error querying gallery: %s", err.Error())
}
// convert criterion value to the 100 value
ratingCriterion.Value = models.Rating5To100(ratingCriterion.Value)
for _, gallery := range galleries {
verifyIntPtr(t, gallery.Rating, ratingCriterion)
}
return nil
})
}
func TestGalleryQueryRating100(t *testing.T) {
const rating = 60
ratingCriterion := models.IntCriterionInput{

View file

@ -676,8 +676,6 @@ func (qb *ImageStore) makeFilter(ctx context.Context, imageFilter *models.ImageF
query.handleCriterion(ctx, pathCriterionHandler(imageFilter.Path, "folders.path", "files.basename", qb.addFoldersTable))
query.handleCriterion(ctx, imageFileCountCriterionHandler(qb, imageFilter.FileCount))
query.handleCriterion(ctx, intCriterionHandler(imageFilter.Rating100, "images.rating", nil))
// legacy rating handler
query.handleCriterion(ctx, rating5CriterionHandler(imageFilter.Rating, "images.rating", nil))
query.handleCriterion(ctx, intCriterionHandler(imageFilter.OCounter, "images.o_counter", nil))
query.handleCriterion(ctx, boolCriterionHandler(imageFilter.Organized, "images.organized", nil))
query.handleCriterion(ctx, dateCriterionHandler(imageFilter.Date, "images.date"))

View file

@ -1772,54 +1772,6 @@ func TestImageIllegalQuery(t *testing.T) {
})
}
func TestImageQueryLegacyRating(t *testing.T) {
const rating = 3
ratingCriterion := models.IntCriterionInput{
Value: rating,
Modifier: models.CriterionModifierEquals,
}
verifyImagesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierNotEquals
verifyImagesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierGreaterThan
verifyImagesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierLessThan
verifyImagesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierIsNull
verifyImagesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierNotNull
verifyImagesLegacyRating(t, ratingCriterion)
}
func verifyImagesLegacyRating(t *testing.T, ratingCriterion models.IntCriterionInput) {
withTxn(func(ctx context.Context) error {
sqb := db.Image
imageFilter := models.ImageFilterType{
Rating: &ratingCriterion,
}
images, _, err := queryImagesWithCount(ctx, sqb, &imageFilter, nil)
if err != nil {
t.Errorf("Error querying image: %s", err.Error())
}
// convert criterion value to the 100 value
ratingCriterion.Value = models.Rating5To100(ratingCriterion.Value)
for _, image := range images {
verifyIntPtr(t, image.Rating, ratingCriterion)
}
return nil
})
}
func TestImageQueryRating100(t *testing.T) {
const rating = 60
ratingCriterion := models.IntCriterionInput{

View file

@ -334,8 +334,6 @@ func (qb *MovieStore) makeFilter(ctx context.Context, movieFilter *models.MovieF
query.handleCriterion(ctx, stringCriterionHandler(movieFilter.Director, "movies.director"))
query.handleCriterion(ctx, stringCriterionHandler(movieFilter.Synopsis, "movies.synopsis"))
query.handleCriterion(ctx, intCriterionHandler(movieFilter.Rating100, "movies.rating", nil))
// legacy rating handler
query.handleCriterion(ctx, rating5CriterionHandler(movieFilter.Rating, "movies.rating", nil))
query.handleCriterion(ctx, floatIntCriterionHandler(movieFilter.Duration, "movies.duration", nil))
query.handleCriterion(ctx, movieIsMissingCriterionHandler(qb, movieFilter.IsMissing))
query.handleCriterion(ctx, stringCriterionHandler(movieFilter.URL, "movies.url"))

View file

@ -636,8 +636,6 @@ func (qb *PerformerStore) makeFilter(ctx context.Context, filter *models.Perform
query.handleCriterion(ctx, stringCriterionHandler(filter.Tattoos, tableName+".tattoos"))
query.handleCriterion(ctx, stringCriterionHandler(filter.Piercings, tableName+".piercings"))
query.handleCriterion(ctx, intCriterionHandler(filter.Rating100, tableName+".rating", nil))
// legacy rating handler
query.handleCriterion(ctx, rating5CriterionHandler(filter.Rating, tableName+".rating", nil))
query.handleCriterion(ctx, stringCriterionHandler(filter.HairColor, tableName+".hair_color"))
query.handleCriterion(ctx, stringCriterionHandler(filter.URL, tableName+".url"))
query.handleCriterion(ctx, intCriterionHandler(filter.Weight, tableName+".weight", nil))

View file

@ -1719,50 +1719,6 @@ func testPerformerStashIDs(ctx context.Context, t *testing.T, s *models.Performe
assert.Len(t, s.StashIDs.List(), 0)
}
func TestPerformerQueryLegacyRating(t *testing.T) {
const rating = 3
ratingCriterion := models.IntCriterionInput{
Value: rating,
Modifier: models.CriterionModifierEquals,
}
verifyPerformersLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierNotEquals
verifyPerformersLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierGreaterThan
verifyPerformersLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierLessThan
verifyPerformersLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierIsNull
verifyPerformersLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierNotNull
verifyPerformersLegacyRating(t, ratingCriterion)
}
func verifyPerformersLegacyRating(t *testing.T, ratingCriterion models.IntCriterionInput) {
withTxn(func(ctx context.Context) error {
performerFilter := models.PerformerFilterType{
Rating: &ratingCriterion,
}
performers := queryPerformers(ctx, t, &performerFilter, nil)
// convert criterion value to the 100 value
ratingCriterion.Value = models.Rating5To100(ratingCriterion.Value)
for _, performer := range performers {
verifyIntPtr(t, performer.Rating, ratingCriterion)
}
return nil
})
}
func TestPerformerQueryRating100(t *testing.T) {
const rating = 60
ratingCriterion := models.IntCriterionInput{

View file

@ -976,8 +976,6 @@ func (qb *SceneStore) makeFilter(ctx context.Context, sceneFilter *models.SceneF
query.handleCriterion(ctx, scenePhashDistanceCriterionHandler(qb, sceneFilter.PhashDistance))
query.handleCriterion(ctx, intCriterionHandler(sceneFilter.Rating100, "scenes.rating", nil))
// legacy rating handler
query.handleCriterion(ctx, rating5CriterionHandler(sceneFilter.Rating, "scenes.rating", nil))
query.handleCriterion(ctx, intCriterionHandler(sceneFilter.OCounter, "scenes.o_counter", nil))
query.handleCriterion(ctx, boolCriterionHandler(sceneFilter.Organized, "scenes.organized", nil))

View file

@ -2673,51 +2673,6 @@ func verifyString(t *testing.T, value string, criterion models.StringCriterionIn
}
}
func TestSceneQueryRating(t *testing.T) {
const rating = 3
ratingCriterion := models.IntCriterionInput{
Value: rating,
Modifier: models.CriterionModifierEquals,
}
verifyScenesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierNotEquals
verifyScenesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierGreaterThan
verifyScenesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierLessThan
verifyScenesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierIsNull
verifyScenesLegacyRating(t, ratingCriterion)
ratingCriterion.Modifier = models.CriterionModifierNotNull
verifyScenesLegacyRating(t, ratingCriterion)
}
func verifyScenesLegacyRating(t *testing.T, ratingCriterion models.IntCriterionInput) {
withTxn(func(ctx context.Context) error {
sqb := db.Scene
sceneFilter := models.SceneFilterType{
Rating: &ratingCriterion,
}
scenes := queryScene(ctx, t, sqb, &sceneFilter, nil)
// convert criterion value to the 100 value
ratingCriterion.Value = models.Rating5To100(ratingCriterion.Value)
for _, scene := range scenes {
verifyIntPtr(t, scene.Rating, ratingCriterion)
}
return nil
})
}
func TestSceneQueryRating100(t *testing.T) {
const rating = 60
ratingCriterion := models.IntCriterionInput{

View file

@ -496,8 +496,6 @@ func (qb *StudioStore) makeFilter(ctx context.Context, studioFilter *models.Stud
query.handleCriterion(ctx, stringCriterionHandler(studioFilter.Details, studioTable+".details"))
query.handleCriterion(ctx, stringCriterionHandler(studioFilter.URL, studioTable+".url"))
query.handleCriterion(ctx, intCriterionHandler(studioFilter.Rating100, studioTable+".rating", nil))
// legacy rating handler
query.handleCriterion(ctx, rating5CriterionHandler(studioFilter.Rating, studioTable+".rating", nil))
query.handleCriterion(ctx, boolCriterionHandler(studioFilter.IgnoreAutoTag, studioTable+".ignore_auto_tag", nil))
query.handleCriterion(ctx, criterionHandlerFunc(func(ctx context.Context, f *filterBuilder) {

View file

@ -672,7 +672,7 @@ func TestStudioQueryURL(t *testing.T) {
}
func TestStudioQueryRating(t *testing.T) {
const rating = 3
const rating = 60
ratingCriterion := models.IntCriterionInput{
Value: rating,
Modifier: models.CriterionModifierEquals,
@ -718,7 +718,7 @@ func verifyStudiosRating(t *testing.T, ratingCriterion models.IntCriterionInput)
withTxn(func(ctx context.Context) error {
sqb := db.Studio
studioFilter := models.StudioFilterType{
Rating: &ratingCriterion,
Rating100: &ratingCriterion,
}
studios, _, err := sqb.Query(ctx, &studioFilter, nil)
@ -959,7 +959,7 @@ func TestStudioQueryFast(t *testing.T) {
URL: &testStringCriterion,
}
ratingFilter := models.StudioFilterType{
Rating: &testIntCriterion,
Rating100: &testIntCriterion,
}
sceneCountFilter := models.StudioFilterType{
SceneCount: &testIntCriterion,

View file

@ -94,7 +94,7 @@ export const IdentifyDialog: React.FC<IIdentifyDialogProps> = ({
})
);
const scrapers = scraperData.listSceneScrapers;
const scrapers = scraperData.listScrapers;
const fragmentScrapers = scrapers.filter((s) =>
s.scene?.supported_scrapes.includes(GQL.ScrapeType.Fragment)

View file

@ -170,10 +170,8 @@ export const GalleryEditPanel: React.FC<IProps> = ({
});
useEffect(() => {
const newQueryableScrapers = (
Scrapers?.data?.listGalleryScrapers ?? []
).filter((s) =>
s.gallery?.supported_scrapes.includes(GQL.ScrapeType.Fragment)
const newQueryableScrapers = (Scrapers?.data?.listScrapers ?? []).filter(
(s) => s.gallery?.supported_scrapes.includes(GQL.ScrapeType.Fragment)
);
setQueryableScrapers(newQueryableScrapers);
@ -282,7 +280,7 @@ export const GalleryEditPanel: React.FC<IProps> = ({
}
function urlScrapable(scrapedUrl: string): boolean {
return (Scrapers?.data?.listGalleryScrapers ?? []).some((s) =>
return (Scrapers?.data?.listScrapers ?? []).some((s) =>
(s?.gallery?.urls ?? []).some((u) => scrapedUrl.includes(u))
);
}

View file

@ -207,7 +207,7 @@ export const MovieEditPanel: React.FC<IMovieEditPanel> = ({
function urlScrapable(scrapedUrl: string) {
return (
!!scrapedUrl &&
(Scrapers?.data?.listMovieScrapers ?? []).some((s) =>
(Scrapers?.data?.listScrapers ?? []).some((s) =>
(s?.movie?.urls ?? []).some((u) => scrapedUrl.includes(u))
)
);

View file

@ -46,7 +46,7 @@ const performerFields = [
"country",
"ethnicity",
"eye_color",
"height",
// "height",
// "weight",
"measurements",
"fake_tits",
@ -69,7 +69,8 @@ export const EditPerformersDialog: React.FC<IListOperationProps> = (
const [existingTagIds, setExistingTagIds] = useState<string[]>();
const [aggregateState, setAggregateState] =
useState<GQL.BulkPerformerUpdateInput>({});
// weight needs conversion to/from number
// height and weight needs conversion to/from number
const [height, setHeight] = useState<string | undefined>();
const [weight, setWeight] = useState<string | undefined>();
const [penis_length, setPenisLength] = useState<string | undefined>();
const [updateInput, setUpdateInput] = useState<GQL.BulkPerformerUpdateInput>(
@ -114,6 +115,9 @@ export const EditPerformersDialog: React.FC<IListOperationProps> = (
aggregateState.circumcised
);
if (height !== undefined) {
performerInput.height_cm = parseFloat(height);
}
if (weight !== undefined) {
performerInput.weight = parseFloat(weight);
}
@ -151,6 +155,7 @@ export const EditPerformersDialog: React.FC<IListOperationProps> = (
const state = props.selected;
let updateTagIds: string[] = [];
let updateHeight: string | undefined | null = undefined;
let updateWeight: string | undefined | null = undefined;
let updatePenisLength: string | undefined | null = undefined;
let first = true;
@ -163,6 +168,12 @@ export const EditPerformersDialog: React.FC<IListOperationProps> = (
updateTagIds =
getAggregateState(updateTagIds, performerTagIDs, first) ?? [];
const thisHeight =
performer.height_cm !== undefined && performer.height_cm !== null
? performer.height_cm.toString()
: performer.height_cm;
updateHeight = getAggregateState(updateHeight, thisHeight, first);
const thisWeight =
performer.weight !== undefined && performer.weight !== null
? performer.weight.toString()
@ -183,6 +194,7 @@ export const EditPerformersDialog: React.FC<IListOperationProps> = (
});
setExistingTagIds(updateTagIds);
setHeight(updateHeight);
setWeight(updateWeight);
setAggregateState(updateState);
setUpdateInput(updateState);
@ -291,9 +303,7 @@ export const EditPerformersDialog: React.FC<IListOperationProps> = (
{renderTextField("eye_color", updateInput.eye_color, (v) =>
setUpdateField({ eye_color: v })
)}
{renderTextField("height", updateInput.height, (v) =>
setUpdateField({ height: v })
)}
{renderTextField("height", height, (v) => setHeight(v))}
{renderTextField("weight", weight, (v) => setWeight(v))}
{renderTextField("measurements", updateInput.measurements, (v) =>
setUpdateField({ measurements: v })

View file

@ -492,10 +492,8 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
});
useEffect(() => {
const newQueryableScrapers = (
Scrapers?.data?.listPerformerScrapers ?? []
).filter((s) =>
s.performer?.supported_scrapes.includes(GQL.ScrapeType.Name)
const newQueryableScrapers = (Scrapers?.data?.listScrapers ?? []).filter(
(s) => s.performer?.supported_scrapes.includes(GQL.ScrapeType.Name)
);
setQueryableScrapers(newQueryableScrapers);
@ -657,7 +655,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
function urlScrapable(scrapedUrl?: string) {
return (
!!scrapedUrl &&
(Scrapers?.data?.listPerformerScrapers ?? []).some((s) =>
(Scrapers?.data?.listScrapers ?? []).some((s) =>
(s?.performer?.urls ?? []).some((u) => scrapedUrl.includes(u))
)
);

View file

@ -232,7 +232,7 @@ export const SceneEditPanel: React.FC<IProps> = ({
});
useEffect(() => {
const toFilter = Scrapers?.data?.listSceneScrapers ?? [];
const toFilter = Scrapers?.data?.listScrapers ?? [];
const newFragmentScrapers = toFilter.filter((s) =>
s.scene?.supported_scrapes.includes(GQL.ScrapeType.Fragment)
@ -527,7 +527,7 @@ export const SceneEditPanel: React.FC<IProps> = ({
}
function urlScrapable(scrapedUrl: string): boolean {
return (Scrapers?.data?.listSceneScrapers ?? []).some((s) =>
return (Scrapers?.data?.listScrapers ?? []).some((s) =>
(s?.scene?.urls ?? []).some((u) => scrapedUrl.includes(u))
);
}

View file

@ -185,7 +185,7 @@ export const SettingsScrapingPanel: React.FC = () => {
}
function renderSceneScrapers() {
const elements = (sceneScrapers?.listSceneScrapers ?? []).map((scraper) => (
const elements = (sceneScrapers?.listScrapers ?? []).map((scraper) => (
<tr key={scraper.id}>
<td>{scraper.name}</td>
<td>
@ -205,8 +205,7 @@ export const SettingsScrapingPanel: React.FC = () => {
}
function renderGalleryScrapers() {
const elements = (galleryScrapers?.listGalleryScrapers ?? []).map(
(scraper) => (
const elements = (galleryScrapers?.listScrapers ?? []).map((scraper) => (
<tr key={scraper.id}>
<td>{scraper.name}</td>
<td>
@ -214,8 +213,7 @@ export const SettingsScrapingPanel: React.FC = () => {
</td>
<td>{renderURLs(scraper.gallery?.urls ?? [])}</td>
</tr>
)
);
));
return renderTable(
intl.formatMessage(
@ -227,8 +225,7 @@ export const SettingsScrapingPanel: React.FC = () => {
}
function renderPerformerScrapers() {
const elements = (performerScrapers?.listPerformerScrapers ?? []).map(
(scraper) => (
const elements = (performerScrapers?.listScrapers ?? []).map((scraper) => (
<tr key={scraper.id}>
<td>{scraper.name}</td>
<td>
@ -238,8 +235,7 @@ export const SettingsScrapingPanel: React.FC = () => {
</td>
<td>{renderURLs(scraper.performer?.urls ?? [])}</td>
</tr>
)
);
));
return renderTable(
intl.formatMessage(
@ -251,7 +247,7 @@ export const SettingsScrapingPanel: React.FC = () => {
}
function renderMovieScrapers() {
const elements = (movieScrapers?.listMovieScrapers ?? []).map((scraper) => (
const elements = (movieScrapers?.listScrapers ?? []).map((scraper) => (
<tr key={scraper.id}>
<td>{scraper.name}</td>
<td>

View file

@ -141,7 +141,7 @@ export const TaggerContext: React.FC = ({ children }) => {
}
const { stashBoxes } = stashConfig.general;
const scrapers = Scrapers.data.listSceneScrapers;
const scrapers = Scrapers.data.listScrapers;
const stashboxSources: ITaggerSource[] = stashBoxes.map((s, i) => ({
id: `${STASH_BOX_PREFIX}${i}`,

View file

@ -1,61 +1,10 @@
import * as GQL from "src/core/generated-graphql";
import sortBy from "lodash-es/sortBy";
import {
evictQueries,
getClient,
studioMutationImpactedQueries,
} from "src/core/StashService";
export const useUpdatePerformerStashID = () => {
const [updatePerformer] = GQL.usePerformerUpdateMutation({
onError: (errors) => errors,
});
const updatePerformerHandler = (
performerID: string,
stashIDs: GQL.StashIdInput[]
) =>
updatePerformer({
variables: {
input: {
id: performerID,
stash_ids: stashIDs.map((s) => ({
stash_id: s.stash_id,
endpoint: s.endpoint,
})),
},
},
update: (store, updatedPerformer) => {
if (!updatedPerformer.data?.performerUpdate) return;
const newStashID = stashIDs[stashIDs.length - 1].stash_id;
store.writeQuery<
GQL.FindPerformersQuery,
GQL.FindPerformersQueryVariables
>({
query: GQL.FindPerformersDocument,
variables: {
performer_filter: {
stash_id: {
value: newStashID,
modifier: GQL.CriterionModifier.Equals,
},
},
},
data: {
findPerformers: {
count: 1,
performers: [updatedPerformer.data.performerUpdate],
__typename: "FindPerformersResultType",
},
},
});
},
});
return updatePerformerHandler;
};
export const useUpdatePerformer = () => {
const [updatePerformer] = GQL.usePerformerUpdateMutation({
onError: (errors) => errors,
@ -78,8 +27,9 @@ export const useUpdatePerformer = () => {
query: GQL.FindPerformersDocument,
variables: {
performer_filter: {
stash_id: {
value: id.stash_id,
stash_id_endpoint: {
stash_id: id.stash_id,
endpoint: id.endpoint,
modifier: GQL.CriterionModifier.Equals,
},
},
@ -99,91 +49,6 @@ export const useUpdatePerformer = () => {
return updatePerformerHandler;
};
export const useCreatePerformer = () => {
const [createPerformer] = GQL.usePerformerCreateMutation({
onError: (errors) => errors,
});
const handleCreate = (performer: GQL.PerformerCreateInput, stashID: string) =>
createPerformer({
variables: { input: performer },
update: (store, newPerformer) => {
if (!newPerformer?.data?.performerCreate) return;
store.writeQuery<
GQL.FindPerformersQuery,
GQL.FindPerformersQueryVariables
>({
query: GQL.FindPerformersDocument,
variables: {
performer_filter: {
stash_id: {
value: stashID,
modifier: GQL.CriterionModifier.Equals,
},
},
},
data: {
findPerformers: {
count: 1,
performers: [newPerformer.data.performerCreate],
__typename: "FindPerformersResultType",
},
},
});
},
});
return handleCreate;
};
export const useUpdateStudioStashID = () => {
const [updateStudio] = GQL.useStudioUpdateMutation({
onError: (errors) => errors,
});
const handleUpdate = (
studio: GQL.SlimStudioDataFragment,
stashIDs: GQL.StashIdInput[]
) =>
updateStudio({
variables: {
input: {
id: studio.id,
stash_ids: stashIDs.map((s) => ({
stash_id: s.stash_id,
endpoint: s.endpoint,
})),
},
},
update: (store, result) => {
if (!result.data?.studioUpdate) return;
const newStashID = stashIDs[stashIDs.length - 1].stash_id;
store.writeQuery<GQL.FindStudiosQuery, GQL.FindStudiosQueryVariables>({
query: GQL.FindStudiosDocument,
variables: {
studio_filter: {
stash_id: {
value: newStashID,
modifier: GQL.CriterionModifier.Equals,
},
},
},
data: {
findStudios: {
count: 1,
studios: [result.data.studioUpdate],
__typename: "FindStudiosResultType",
},
},
});
},
});
return handleUpdate;
};
export const useUpdateStudio = () => {
const [updateStudio] = GQL.useStudioUpdateMutation({
onError: (errors) => errors,
@ -210,8 +75,9 @@ export const useUpdateStudio = () => {
query: GQL.FindStudiosDocument,
variables: {
studio_filter: {
stash_id: {
value: id.stash_id,
stash_id_endpoint: {
stash_id: id.stash_id,
endpoint: id.endpoint,
modifier: GQL.CriterionModifier.Equals,
},
},
@ -231,101 +97,3 @@ export const useUpdateStudio = () => {
return updateStudioHandler;
};
export const useCreateStudio = () => {
const [createStudio] = GQL.useStudioCreateMutation({
onError: (errors) => errors,
});
const handleCreate = (studio: GQL.StudioCreateInput, stashID: string) =>
createStudio({
variables: { input: studio },
update: (store, result) => {
if (!result?.data?.studioCreate) return;
const currentQuery = store.readQuery<
GQL.AllStudiosForFilterQuery,
GQL.AllStudiosForFilterQueryVariables
>({
query: GQL.AllStudiosForFilterDocument,
});
const allStudios = sortBy(
[...(currentQuery?.allStudios ?? []), result.data.studioCreate],
["name"]
);
if (allStudios.length > 1) {
store.writeQuery<
GQL.AllStudiosForFilterQuery,
GQL.AllStudiosForFilterQueryVariables
>({
query: GQL.AllStudiosForFilterDocument,
data: {
allStudios,
},
});
}
store.writeQuery<GQL.FindStudiosQuery, GQL.FindStudiosQueryVariables>({
query: GQL.FindStudiosDocument,
variables: {
studio_filter: {
stash_id: {
value: stashID,
modifier: GQL.CriterionModifier.Equals,
},
},
},
data: {
findStudios: {
count: 1,
studios: [result.data.studioCreate],
__typename: "FindStudiosResultType",
},
},
});
},
});
return handleCreate;
};
export const useCreateTag = () => {
const [createTag] = GQL.useTagCreateMutation({
onError: (errors) => errors,
});
const handleCreate = (tag: string) =>
createTag({
variables: {
input: {
name: tag,
},
},
update: (store, result) => {
if (!result.data?.tagCreate) return;
const currentQuery = store.readQuery<
GQL.AllTagsForFilterQuery,
GQL.AllTagsForFilterQueryVariables
>({
query: GQL.AllTagsForFilterDocument,
});
const allTags = sortBy(
[...(currentQuery?.allTags ?? []), result.data.tagCreate],
["name"]
);
store.writeQuery<
GQL.AllTagsForFilterQuery,
GQL.AllTagsForFilterQueryVariables
>({
query: GQL.AllTagsForFilterDocument,
data: {
allTags,
},
});
},
});
return handleCreate;
};

View file

@ -15,15 +15,15 @@ export const scrapedMovieToCreateInput = (toCreate: GQL.ScrapedMovie) => {
? DurationUtils.stringToSeconds(toCreate.duration)
: undefined,
studio_id: toCreate.studio?.stored_id,
rating: parseInt(toCreate.rating ?? "0", 10),
rating100: parseInt(toCreate.rating ?? "0", 10) * 20,
};
if (!input.duration) {
input.duration = undefined;
}
if (!input.rating || Number.isNaN(input.rating)) {
input.rating = undefined;
if (!input.rating100 || Number.isNaN(input.rating100)) {
input.rating100 = undefined;
}
return input;

View file

@ -86,6 +86,8 @@ export function sortPerformers<T extends IPerformerFragment>(performers: T[]) {
export const scrapedPerformerToCreateInput = (
toCreate: GQL.ScrapedPerformer
) => {
const aliases = toCreate.aliases?.split(",").map((a) => a.trim());
const input: GQL.PerformerCreateInput = {
name: toCreate.name ?? "",
url: toCreate.url,
@ -100,7 +102,7 @@ export const scrapedPerformerToCreateInput = (
career_length: toCreate.career_length,
tattoos: toCreate.tattoos,
piercings: toCreate.piercings,
aliases: toCreate.aliases,
alias_list: aliases,
twitter: toCreate.twitter,
instagram: toCreate.instagram,
tag_ids: filterData((toCreate.tags ?? []).map((t) => t.stored_id)),